LEFT JOIN dictionaries in python based on value

Viewed 2389
#Input
dict_1 = {"conn": {"ts":15,"uid":"ABC","orig_h":"10.10.210.250"}}
dict_2 = {"conn": {"ts":15,"uid":"ABC","orig_h":"10.10.210.252"}}

#Mapper can be modified as required
mapper = {"10.10.210.250":"black","192.168.2.1":"black"} 

I am getting each dict in a loop, in each iteration I need to check a dict against the mapper and append a flag based on match between dict_1.orig_h and mapper.10.10.210.250 . I have the flexibility to define the mapper however I need.

So the desired result would be:

dict_1 = {"conn": {"ts":15,"uid":"ABC","orig_h":"10.10.210.250", "class":"black"}}

dict_2 will remain unchanged since there is no matching value in mapper.

This is kinda what I want, but it works only if orig_h is an int

import collections
result = collections.defaultdict(dict)
for d in dict_1:
    result[d[int('orig_h')]].update(d)
for d in mapper:
    result[d[int('orig_h')]].update(d)
3 Answers

Not much explaining to be done; if the ip is in the mapper dictionary (if mapper has a key which is that ip) then set the desired attribute of the dict to the value of the key in the mapper dict ('black' here).

def update_dict(dic, mapper):
    ip = dic['conn']['orig_h']
    if ip in mapper:
        dic['conn']['class'] = mapper[ip]

which works exactly as desired:

>>> update_dict(dict_1, mapper)
>>> dict_1
{'conn': {'ts': 15, 'uid': 'ABC', 'orig_h': '10.10.210.250', 'class': 'black'}}
>>> update_dict(dict_2, mapper)
>>> dict_2
{'conn': {'ts': 15, 'uid': 'ABC', 'orig_h': '10.10.210.252'}}

Extracting the conn value for simplicity:

conn_data = dict_1['conn']
conn_data['class'] = mapper[conn_data['orig_h']]

A two liner, extracting class and dict if the 'orig_h' is in the mapper dictionary's keys, if it id, keep it, otherwise don't keep it, then create a new dictionary comprehension inside the list comprehension to add 'class' to the dictionary's 'conn' key's dictionary.

l=[(i,mapper[i['conn']['orig_h']]) for i in (dict_1,dict_2) if i['conn']['orig_h'] in mapper]
print([{'conn':dict(a['conn'],**{'class':b})} for a,b in l])

BTW this answer chooses the dictionaries automatically

Related