Home > Software design >  Extract differences of values of 2 given dictionaries - values are tuples of strings
Extract differences of values of 2 given dictionaries - values are tuples of strings

Time:08-20

I have two dictionaries as follows, I need to extract which strings in the tuple values are in one dictionary but not in other:

dict_a = {"s": ("mmmm", "iiiii", "p11"), "yyzz": ("oo", "i9")}
dict_b = {"s": ("mmmm",), "h": ("pp",), "g": ("rr",)}

The desired output:

{"s": ("iiiii", "p11"), "yyzz": ("oo", "i9")}

The order of the strings in the output doesn't matter.

One way that I tried to solve, but it doesn't produce the expected result:

>>> [item for item in dict_a.values() if item not in dict_b.values()]
[('mmmm', 'iiiii', 'p11'), ('oo', 'i9')]

CodePudding user response:

If order doesn't matter, convert your dictionary values to sets, and subtract these:

{k: set(v) - set(dict_b.get(k, ())) for k, v in dict_a.items()}

The above takes all key-value pairs from dict_a, and for each such pair, outputs a new dictionary with those keys and a new value that's the set difference between the original value and the corresponding value from dict_b, if there is one:

>>> dict_a = {"s": ("mmmm", "iiiii", "p11"), "yyzz": ("oo", "i9")}
>>> dict_b = {"s": ("mmmm",), "h": ("pp",), "g": ("rr",)}
>>> {k: set(v) - set(dict_b.get(k, ())) for k, v in dict_a.items()}
{'s': {'p11', 'iiiii'}, 'yyzz': {'oo', 'i9'}}

The output will have sets, but these can be converted back to tuples if necessary:

{k: tuple(set(v) - set(dict_b.get(k, ()))) for k, v in dict_a.items()}

The dict_b.get(k, ()) call ensures there is always a tuple to give to set().

If you use the set.difference() method you don't even need to turn the dict_b value to a set:

{k: tuple(set(v).difference(dict_b.get(k, ()))) for k, v in dict_a.items()}

Demo of the latter two options:

>>> {k: tuple(set(v) - set(dict_b.get(k, ()))) for k, v in dict_a.items()}
{'s': ('p11', 'iiiii'), 'yyzz': ('oo', 'i9')}
>>> {k: tuple(set(v).difference(dict_b.get(k, ()))) for k, v in dict_a.items()}
{'s': ('p11', 'iiiii'), 'yyzz': ('oo', 'i9')}

CodePudding user response:

{k: [v for v in vs if v not in dict_b.get(k, [])] for k,vs in dict_a.items()}

if you want to use tuples (or sets - just replace the cast)

{k: tuple(v for v in vs if v not in dict_b.get(k, [])) for k,vs in dict_a.items()}

CodePudding user response:

Try this (see comments for explanations):

>>> out = {} # Initialise output dictionary
>>> for k, v in dict_a.items(): # Iterate through items of dict_a
...     if k not in dict_b: # Check if the key is not in dict_b
...         out[k] = v # If it isn't, add to out
...     else: # Otherwise
...         out[k] = tuple(set(v) - set(dict_b[k])) # Subtract sets to find the difference
...
>>> out
{'s': ('iiiii', 'p11'), 'yyzz': ('oo', 'i9')}

This can then be simplified using a dictionary comprehension:

>>> out = {k: tuple(set(v) - set(dict_b.get(k, ()))) for k, v in dict_a.items()}
>>> out
{'s': ('iiiii', 'p11'), 'yyzz': ('oo', 'i9')}

CodePudding user response:

See this solution :

  • First iterate through all keys in dict_a

  • Check if the key is present or not in dict_b

  • Now, if present: take the tuples and iterate through dict_a's tuple(as per your question). now check weather that element is present or not in dict_b's tuple. If it is present just leave it. If it is not just add that element in tup_res.

  • Now after the for loop, add that key and tup value in the dict_res.

  • if the key is not present in dict_b simply add it in dict_res.


dict_a = {"s":("mmmm","iiiii","p11"), "yyzz":("oo","i9")}
dict_b = {"s":("mmmm"),"h":("pp",),"g":("rr",)}

dict_res = {}

for key in dict_a:
    if key in dict_b:
        tup_a = dict_a[key]
        tup_b = dict_b[key]
        tup_res = ()
        for tup_ele in tup_a:
            if tup_ele in tup_b:
                pass
            else:
                tup_res = tup_res   (tup_ele,)
        dict_res[key] = tup_res;
    else:
        dict_res[key] = dict_a[key];
print(dict_res)

It is giving correct output :)

  • Related