Iterate through list of dictionories and compare with other dictionories

Viewed 88

I have the following dictionaries

dic1 = { 'T1': "HI , china" , 'T2': "HI , finland" ,'T3': "HI , germany"}

dic2 = { 'T1': ['INC1','INC2','INC3'] , 'T2': ['INC2','INC4','INC5'],'T3': ['INC2','INC5']}

dic3 = { 'INC1': {'location':'china'} , 'INC2': {'location':'germany'},'INC3': {'location':'germany'},'INC4': {'location':'finland'}} 

I need to remove the values in dic2 based on the dic1,dic3

example :

  1. I have to iterate through dic2 first and check the T1 and its INC values.
  2. If the corresponding T1 key value in the Dic1 matches with the corresponding INC values in the dic3 the keep the value in dic2 otherwise pop the value.

Detaileded explanation given in the picture. And I am expecting the following output.

dic2 = { 'T1': ['INC1'] , 'T2': ['INC4'],'T3': ['INC2']}

enter image description here

example code :

for k, v in dic2.items():
for k1, v1 in dic1.items():
    if k is k1:
        print k
        for k2 in v:
            for k3 in dic3.items():
  

I am new to python. I have tried the above pieces of code and I got struck down.Could you please help me out.

3 Answers

Can be done in a one-liner:

>>> {k: [i for i in v if dic3.get(i, {}).get('location', '#') in dic1[k]] for k, v in dic2.items()}
{'T1': ['INC1'], 'T2': ['INC4'], 'T3': ['INC2']}

[i for i in v if dic3.get(i, {}).get('location', '#') is the list comprehension to pick only the values from dic2's lists if dic3[i]['location'] is inside dic1[k], where i is the key in dict d3 and k is the key from dict d2 as well as dict d1.

I used dic3.get(i, {}).get('location', '#') (rather than dic3[i]['location'], you get KeyError for key INC5 which is not in dic3) to avoid the issue of key i not being in dic3 (would return an empty dict for my next .get) and in the second .get, again I use it to return the location key's corresponding value if it exists and check if that returned string lies inside the values of dict d1.

I return # (can be any string/char) if I know that the key i doesn’t exist in dic3 (i not existing will essentially give {}.get('location', '#') which in turn will give #, this is sure to fail the membership in d1, hence it's Ok).

Toned down for-loop version:

>>> ans = {}
>>> for k, v in dic2.items():
...     temp = []
...     for i in v:
...             if i in dic3 and dic3[i]['location'] in dic1[k]:
...                     temp.append(i)
...     ans[k] = temp
... 
>>> ans
{'T1': ['INC1'], 'T2': ['INC4'], 'T3': ['INC2']}

From my understanding, you are supposed to modify the original dic2 dictionary rather than creating a new one for your answer, this is what I got:

delete = []

for key, value in dic2.items():
    loc = dic1[key][5:]
    for inc in value:
        if inc not in dic3:
            delete.append(inc)
        else:
            if loc != dic3.get(inc)['location']:
                delete.append(inc)

    for item in delete:
        value.remove(item)
    delete = []

print(dic2)

>>> {'T1': ['INC1'], 'T2': ['INC4'], 'T3': ['INC2']}

The first for loop iterates through dic2 and sets the location required to the variable loc. The next one iterates through the lists (values) and adds them to a delete list. At the end of each loop, it iterates through the delete list, removing each element from the value list, and then setting delete to an empty list.

I am also relatively new to python so I am sure there could be efficiency issues.

This is essentially the same as the other answers but as a one-liner, it may be more readable (maybe not, since it's subjective).

{k: [el] for k, v in dic2.items() for el in v if (el in dic3.keys() and dic3[el]['location'] in dic1[k])}
Related