简体   繁体   中英

Appending value to dict key if dict is “similar” to another one

First of all, sorry for the title, I couldn't think of a good one to be honest.

I have a list of dictionaries like this

data=[
{'identifier': 'ID', 'resource': 'resource1' , 'name': 'name1'},
{'identifier': 'ID', 'resource': 'resource2' , 'name': 'name1'},
{'identifier': 'ID', 'resource': 'resource3' , 'name': 'name1'},
{'identifier': 'ID', 'resource': 'resource1' , 'name': 'name2'},
{'identifier': 'ID', 'resource': 'resource2' , 'name': 'name2'},
{'identifier': 'ID', 'resource': 'resource3' , 'name': 'name2'}
]

Basically, I want a dict that contains the name and every resource with that name, something like this

final = [
{
'name': 'name1',
'resources': ['resource1','resource2','resource3']
},
{
'name': 'name2',
'resources': ['resource1','resource2','resource3']
}
]

I have tried some approaches, like iterating over the first list and verifying if the key value pair already exists on the second one, so after that I can append the resource to the key I want but clearly thats not the correct way to do it.

Im sure there's a way to easily do this but I cant wrap my head around on how to achieve it. Any ideas on how can this be done?

Group with a collections.defaultdict , with name as the grouping key and the resources for each name appended to a list:

from collections import defaultdict

data = [
    {"identifier": "ID", "resource": "resource1", "name": "name1"},
    {"identifier": "ID", "resource": "resource2", "name": "name1"},
    {"identifier": "ID", "resource": "resource3", "name": "name1"},
    {"identifier": "ID", "resource": "resource1", "name": "name2"},
    {"identifier": "ID", "resource": "resource2", "name": "name2"},
    {"identifier": "ID", "resource": "resource3", "name": "name2"},
]

d = defaultdict(list)
for x in data:
    d[x["name"]].append(x["resource"])

result = [{"name": k, "resources": v} for k, v in d.items()]

print(result)

However, since your names are ordered, we can also get away with using itertools.groupby :

from itertools import groupby
from operator import itemgetter

result = [
    {"name": k, "resources": [x["resource"] for x in g]}
    for k, g in groupby(data, key=itemgetter("name"))
]

print(result)

If your names are not ordered, then we will need to sort data by name :

result = [
    {"name": k, "resources": [x["resource"] for x in g]}
    for k, g in groupby(sorted(data, key=itemgetter("name")), key=itemgetter("name"))
]

print(result)

Output:

[{'name': 'name1', 'resources': ['resource1', 'resource2', 'resource3']}, {'name': 'name2', 'resources': ['resource1', 'resource2', 'resource3']}]

Note: I would probably just stick with the first defaultdict solution in most cases, because it doesn't care about order.

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