python - Combine dicts in a list if they have the same key -
i have dict looks this:
{'item1': [{'name1': 3}, {'name2': 4}, {'name1':7}], 'item2': [{'name7': 44}, {'name2': 3}, {'name6':9}, {'name6':2}] }
i want combine dictionaries in list attached key such if there multiple dicts same key, can combine them (sum) , leave others are.
the output like:
{'item1': [{'name1': 10}, {'name2': 4}], 'item2': [{'name7': 44}, {'name2': 3}, {'name6': 11}] }
i can't figure out how in python elegantly list/dict comprehension.
this uses collections.counter. elegant come with, because of convoluted structure of input - list of 1-length dictionaries indeed better implemented single dictionary, comments suggest. code transforms to, although have provided more possible tranformations if direly need old data structure. if do, recommend using tuples key-value pairs rather single-length dicts, seen in tuple_output
. recommend use output
or dict_output
.
from collections import counter d = {'item1': [{'name1': 3}, {'name2': 4}, {'name1':7}], 'item2': [{'name7': 44}, {'name2': 3}, {'name6':9}, {'name6':2}] } output = {} k, v in d.items(): c = counter() sub_dict in v: c.update(sub_dict) output[k] = c dict_output = {k: dict(v) k, v in output.items()} tuple_output = {k: v.most_common() k, v in output.items()} dict_list_output = {k: [{a: b} a, b in v.most_common()] k, v in output.items()} print(output) #{'item1': counter({'name1': 10, 'name2': 4}), 'item2': counter({'name7': 44, 'name6': 11, 'name2': 3})} print(dict_output) #{'item1': {'name1': 10, 'name2': 4}, 'item2': {'name7': 44, 'name2': 3, 'name6': 11}} print(tuple_output) #{'item1': [('name1', 10), ('name2', 4)], 'item2': [('name7', 44), ('name6', 11), ('name2', 3)]} print(dict_list_output) #{'item1': [{'name1': 10}, {'name2': 4}], 'item2': [{'name7': 44}, {'name6': 11}, {'name2': 3}]}
of course, if change starting data structure altogether, become lot easier manage. if use dictionary strings counters, can use counter interface update (refer link)
edit:
just fun, done in 1 line:
results = {item: reduce(lambda a, b: [a, a.update(b)][0], names, counter()) item, names in d.items()}
it inspired yours, except builds 1 counter instance (given initial value reduce) per list. also, little bit of golfy trick required reduce properly, counter.update in place. if you're reading this, shouldn't use it, , instead build data structure counters or dicts start, mentioned earlier.
Comments
Post a Comment