简体   繁体   中英

How to combine dictionaries within an array based on the same key-value pairs?

For example in the below list, I'd like to combine all dictionaries that share the same 'id' and 'name.'

Input:

l = [{'id':'1','name':'a','key1':'1'},
     {'id':'1','name':'a','key2':'3'},
     {'id':'1','name':'a','key3':'4'},
     {'id':'2','name':'a','key5':'1'},
     {'id':'2','name':'a','key7':'c'},
     {'id':'1','name':'b','key5':'1'}]

Desired Result:

l = [{'id':'1','name':'a','key1':'1','key2':'3','key3':'4'},
     {'id':'2','name':'a','key5':'1','key7':'c'},
     {'id':'1','name':'b','key5':'1'}]

If possible, I'd like the function to also take different number of arguments for which keys the dictionaries would have to share for them to combine. For example, if I just wanted to combine based on just the 'id' instead of the 'key' and the 'name,' the result would be different.

itertools.groupby does the grouping for you. All that's left to do then is to merge the list of iterables of dictionaries (grouped by id) into a list of dictionaries:

>>> import itertools    
>>> l = [ dict(reduce(lambda a, b: a + b.items(), lst, [])) for lst in \
          [ list(grouper) for key, grouper in \
            itertools.groupby(l, lambda x: (x["id"], x["name"])) ] \
        ]
>>> l
[{'id': '1', 'key1': '1', 'key2': '3', 'key3': '4', 'name': 'a'},
 {'id': '2', 'key5': '1', 'key7': 'c', 'name': 'a'},
 {'id': '1', 'key5': '1', 'name': 'b'}]

That's clearly not the most readable version to do it; you should probably use a helper function that merges the dictionaries instead of the nested list comprehensions.

Traditional Way :D

result = []

for item in l :
    check = False
    # check item, is it exist in result yet (r_item)
    for r_item in result :
        if item['id'] == r_item['id'] and item['name'] == r_item['name'] :
            # if found, add all key to r_item ( previous record)
            check = True
            r_item.update( item )
    if check == False :
        # if not found, add item to result (new record)
        result.append( item )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM