Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Intersection of two list of dictionaries based on a key

I have two different list of dictionaries,

list1 = [{'count': 351, 'att_value': 'one'},
         {'count': 332,  'att_value': 'two'},
         {'count': 336,  'att_value': 'six'},
         {'count': 359,  'att_value': 'nine'},
         {'count': 304,  'att_value': 'four'}]

list2 = [{'count': 359,'person_id' : 4},
         {'count': 351, 'person_id' : 12},
         {'count': 381, 'person_id' : 8}]

How to find an intersection of list_A with list_B based on "count" key by including rest of the key as like list_C?

list3 = [{'count':359, 'att_value' : 'nine', 'person_id':4},
         {'count':351, 'att_value' : 'one', 'person_id':12},
         {'count':381, 'att_value' : '-', 'person_id':8}] 

I would like to retain the keys from list2, but with missing values from list1 represented by "-".

like image 581
Mahamutha M Avatar asked Dec 21 '18 06:12

Mahamutha M


People also ask

How do you check if two dictionaries have the same keys and values?

Check if two nested dictionaries are equal in Python To do this task, we are going to use the == operator and this method will help the user to check whether the two given dictionaries are equal or not.

Can dictionaries have lists as keys?

These are things like integers, floats, strings, Booleans, functions. Even tuples can be a key. A dictionary or a list cannot be a key.


2 Answers

You can also use pandas library for this:

In [102]: df1 = pd.DataFrame(list1)
In [104]: df2 = pd.DataFrame(list2)

In [106]: pd.merge(df2,df1, on='count', how='left').fillna('-')
Out[106]: 
     count att_value
0    359      nine
1    351       one
2    381         -
like image 179
Mayank Porwal Avatar answered Oct 19 '22 12:10

Mayank Porwal


You can do this with a list comprehension. First, build a set of all counts from list2, and then filter out dictionaries based on constant time set membership check.

counts = {d2['count'] for d2 in list2}
list3 = [d for d in list1 if d['count'] in counts]

print(list3)
# [{'count': 351, 'att_value': 'one', 'person_id': 12}, 
#  {'count': 359, 'att_value': 'nine', 'person_id': 4}]

(Re:Edit) To handle other keys (besides just "att_value") appropriately, giving a default value of '-' in the same way, you can use:

keys = list1[0].keys() - {'count'}
idx = {d['count'] : d for d in list1}
list3 = []
for d in list2:
    d2 = idx.get(d['count'], dict.fromkeys(keys, '-'))
    d2.update(d)
    list3.append(d2)

print(list3)
# [{'count': 359, 'att_value': 'nine', 'person_id': 4},
#  {'count': 351, 'att_value': 'one', 'person_id': 12},
#  {'person_id': 8, 'att_value': '-', 'count': 381}]
like image 35
cs95 Avatar answered Oct 19 '22 13:10

cs95