Home > Blockchain >  Merge lists of dictionaries based on matching values in one key
Merge lists of dictionaries based on matching values in one key

Time:01-06

I have a dictionary

dicte = [{'value':3, 'content':'some_string'}, {'value':4, 'content':'some_string1'}, {'value':4, 'content':'some_string2'}, {'value':4, 'content':'some_string3'}, {'value':4, 'content':'some_string4'}, {'value':5, 'content':'some_string5'}]

I want to be able to do an operation on that dictionary so that all the content that got the same values regarding the key "value" are regrouped and generate another dictionary based on that

The result here should be

new_dicte = [{'value':3, 'content':['some_string']}, {'value':4, 'content':['some_string1', 'some_string2', 'some_string3', 'some_string4']}, {'value':5, 'content':['some_string5']}]

What is the best pythonic way to do this ?

CodePudding user response:

"Pythonic" is debatable, but you could build an intermediate dict to group by value:

grouped_by_value = {}

for item in dicte:
    if item["value"] not in grouped_by_value:
        grouped_by_value[item["value"]] = []

    grouped_by_value[item["value"]].append(item["content"])

new_dicte = [{"value": key, "content": val} for key, val in grouped_by_value.items()]

The order of the elements in the new_dicte list will be the order that the values are encountered in the dicte list, assuming you are using a Python version where dicts are sorted by insertion order.

If you want to guarantee a specific ordering for new_dicte, you can sort the items of the grouped_by_value.items(), for example, by increasing "value" key.

CodePudding user response:

Here's one way using dict.setdefault method to collect value-content pairs and unpacking later:

out = {}
for d in dicte:
    out.setdefault(d['value'],[]).append(d['content'])
new_dicte = list(map(lambda x: dict(zip(('value','content'), x)), out.items()))

Here's another method that doesn't use an intermediate dictionary:

out = {}
for d in dicte:
    if d['value'] not in out:
        out[d['value']] = {'value':d['value'], 'content':[d['content']]}
    else:
        out[d['value']]['content'].append(d['content'])
new_dicte = list(out.values())

Output:

[{'value': 3, 'content': ['some_string']},
 {'value': 4,
  'content': ['some_string1', 'some_string2', 'some_string3', 'some_string4']},
 {'value': 5, 'content': ['some_string5']}]

CodePudding user response:

Best Pythonic is debatable but I would personally go with something like this,

import itertools
from collections import defaultdict

resp = defaultdict(list)

for key,group in itertools.groupby(d, key=lambda x: x["value"]):
    for thing in group:
        resp[key].append(thing.get("content"))

print(resp)

Output (can be adjusted to the way we want...)

{3: ['some_string'],
 4: ['some_string1', 'some_string2', 'some_string3', 'some_string4'],
 5: ['some_string5']}
  •  Tags:  
  • Related