python:如何基于值在dict列表中合并dict

python:如何基于值在dict列表中合并dict,python,dictionary,grouping,Python,Dictionary,Grouping,我有一个dict列表,其中每个dict由3个键组成:name、url和location。 在整个dicts中只有“name”的值可以相同,“url”和“location”在整个列表中始终是不同的值 例如: 然后我想根据“name”中的值对它们进行分组,如下所示 预期: 实际列表包含>2000条指令 我很高兴能解决这个问题。 如有任何建议/答案,将不胜感激 提前感谢。带有辅助分组dict for Python>3.5: data = [ {"name":"A1", "url":"B1",

我有一个dict列表,其中每个dict由3个键组成:name、url和location。 在整个dicts中只有“name”的值可以相同,“url”和“location”在整个列表中始终是不同的值

例如:

然后我想根据“name”中的值对它们进行分组,如下所示

预期:

实际列表包含>2000条指令

我很高兴能解决这个问题。 如有任何建议/答案,将不胜感激


提前感谢。

带有辅助分组dict for Python>3.5:

data = [
    {"name":"A1", "url":"B1", "location":"C1"}, 
    {"name":"A1", "url":"B2", "location":"C2"}, 
    {"name":"A2", "url":"B3", "location":"C3"},
    {"name":"A2", "url":"B4", "location":"C4"}
]

groups = {}
for d in data:
    if d['name'] not in groups:
        groups[d['name']] = {'url': d['url'], 'location': d['location']}
    else:
        groups[d['name']]['url'] += ', ' + d['url']
        groups[d['name']]['location'] += ', ' + d['location']
result = [{**{'name': k}, **v} for k, v in groups.items()]

print(result)
输出:

[{'name': 'A1', 'url': 'B1, B2', 'location': 'C1, C2'}, {'name': 'A2', 'url': 'B3, B4', 'location': 'C3, C4'}]

对于Python>3.5的辅助分组dict:

data = [
    {"name":"A1", "url":"B1", "location":"C1"}, 
    {"name":"A1", "url":"B2", "location":"C2"}, 
    {"name":"A2", "url":"B3", "location":"C3"},
    {"name":"A2", "url":"B4", "location":"C4"}
]

groups = {}
for d in data:
    if d['name'] not in groups:
        groups[d['name']] = {'url': d['url'], 'location': d['location']}
    else:
        groups[d['name']]['url'] += ', ' + d['url']
        groups[d['name']]['location'] += ', ' + d['location']
result = [{**{'name': k}, **v} for k, v in groups.items()]

print(result)
输出:

[{'name': 'A1', 'url': 'B1, B2', 'location': 'C1, C2'}, {'name': 'A2', 'url': 'B3, B4', 'location': 'C3, C4'}]

使用@Yaroslav Surzhikov comment,下面是一个使用itertools.groupby的解决方案

from itertools import groupby

dicts = [
    {"name":"A1", "url":"B1", "location":"C1"},
    {"name":"A1", "url":"B2", "location":"C2"},
    {"name":"A2", "url":"B3", "location":"C3"},
    {"name":"A2", "url":"B4", "location":"C4"},
]

def merge(dicts):
    new_list = []
    for key, group in groupby(dicts, lambda x: x['name']):
        new_item = {}
        new_item['name'] = key
        new_item['url'] = []
        new_item['location'] = []
        for item in group:
            new_item['url'].extend([item.get('url', '')])
            new_item['location'].extend([item.get('location', '')])
        new_item['url'] = ', '.join(new_item.get('url', ''))
        new_item['location'] = ', '.join(new_item.get('location', ''))
        new_list.append(new_item)
    return new_list

print(merge(dicts))

使用@Yaroslav Surzhikov comment,下面是一个使用itertools.groupby的解决方案

from itertools import groupby

dicts = [
    {"name":"A1", "url":"B1", "location":"C1"},
    {"name":"A1", "url":"B2", "location":"C2"},
    {"name":"A2", "url":"B3", "location":"C3"},
    {"name":"A2", "url":"B4", "location":"C4"},
]

def merge(dicts):
    new_list = []
    for key, group in groupby(dicts, lambda x: x['name']):
        new_item = {}
        new_item['name'] = key
        new_item['url'] = []
        new_item['location'] = []
        for item in group:
            new_item['url'].extend([item.get('url', '')])
            new_item['location'].extend([item.get('location', '')])
        new_item['url'] = ', '.join(new_item.get('url', ''))
        new_item['location'] = ', '.join(new_item.get('location', ''))
        new_list.append(new_item)
    return new_list

print(merge(dicts))

像这样的?小偏差:我更喜欢将URL和位置存储在resDict中的列表中,而不是附加在str中

一行输出:

[
    {'name': 'A2', 'urls': ['B3', 'B4'], 'locations': ['C3', 'C4']}, 
    {'name': 'A1', 'urls': ['B1', 'B2'], 'locations': ['C1', 'C2']}
]

像这样的?小偏差:我更喜欢将URL和位置存储在resDict中的列表中,而不是附加在str中

一行输出:

[
    {'name': 'A2', 'urls': ['B3', 'B4'], 'locations': ['C3', 'C4']}, 
    {'name': 'A1', 'urls': ['B1', 'B2'], 'locations': ['C1', 'C2']}
]
其中res是:

您可以使用defaultdict处理数据,并将结果解压缩到列表中:

from collections import defaultdict

result = defaultdict(lambda: defaultdict(list))

for items in res:
     result[items['name']]['location'].append(items['location'])
     result[items['name']]['url'].append(items['url'])

final = [
    {'name': name, **{inner_names: ' '.join(inner_values) for inner_names, inner_values in values.items()}}
    for name, values in result.items()
]
最后是:

其中res是:

您可以使用defaultdict处理数据,并将结果解压缩到列表中:

from collections import defaultdict

result = defaultdict(lambda: defaultdict(list))

for items in res:
     result[items['name']]['location'].append(items['location'])
     result[items['name']]['url'].append(items['url'])

final = [
    {'name': name, **{inner_names: ' '.join(inner_values) for inner_names, inner_values in values.items()}}
    for name, values in result.items()
]
最后是:


因为你的数据集相对较小,所以我猜想时间复杂度在这里没有什么大不了的,所以你可以考虑下面的代码。

from collections import defaultdict
given_data = [
    {"name":"A1", "url":"B1", "location":"C1"}, 
    {"name":"A1", "url":"B2", "location":"C2"}, 
    {"name":"A2", "url":"B3", "location":"C3"},
    {"name":"A2", "url":"B4", "location":"C4"},
] 
D = defaultdict(list)
for item in given_data:
    D[item['name']].append(item)
result = []
for x in D:
    urls = ""
    locations = ""
    for pp in D[x]:
        urls += pp['url']+" "
        locations += pp['location']+" "
    result.append({'name': x, 'url': urls.strip(), 'location': locations.strip()})

因为你的数据集相对较小,所以我猜想时间复杂度在这里没有什么大不了的,所以你可以考虑下面的代码。

from collections import defaultdict
given_data = [
    {"name":"A1", "url":"B1", "location":"C1"}, 
    {"name":"A1", "url":"B2", "location":"C2"}, 
    {"name":"A2", "url":"B3", "location":"C3"},
    {"name":"A2", "url":"B4", "location":"C4"},
] 
D = defaultdict(list)
for item in given_data:
    D[item['name']].append(item)
result = []
for x in D:
    urls = ""
    locations = ""
    for pp in D[x]:
        urls += pp['url']+" "
        locations += pp['location']+" "
    result.append({'name': x, 'url': urls.strip(), 'location': locations.strip()})
这是一个变体,它甚至很难阅读,感觉就像用左手抓我的右脑,但在这一点上,我不知道如何缩短它,使用:

子句 积累 理解列表和dict 从外部到内部的理由:

根据与名称键itertools.groupby对应的值对初始列表中的词典进行分组 要使其正常工作,一个辅助操作是在分组排序之前按相同的值对列表进行排序 对于每一组这样的字典,执行它们的sum itertools.ACCUMPLE func参数根据键对2个字典求和: 如果键是name,则只需从第一个字典中获取值。无论如何,这两个字典的值是相同的 否则,只需添加中间有空格的2个值字符串 考虑事项:

字典必须保持同质性,所有字典都必须具有相同的结构键 只有name键是硬编码的,但是,如果您决定添加其他非字符串的键,您也必须调整func 为了便于阅读,可以将其拆分 不确定lambdas的性能 这是一个变体,它甚至很难阅读,感觉就像用左手抓我的右脑,但在这一点上,我不知道如何缩短它,使用:

子句 积累 理解列表和dict 从外部到内部的理由:

根据与名称键itertools.groupby对应的值对初始列表中的词典进行分组 要使其正常工作,一个辅助操作是在分组排序之前按相同的值对列表进行排序 对于每一组这样的字典,执行它们的sum itertools.ACCUMPLE func参数根据键对2个字典求和: 如果键是name,则只需从第一个字典中获取值。无论如何,这两个字典的值是相同的 否则,只需添加中间有空格的2个值字符串 考虑事项:

字典必须保持同质性,所有字典都必须具有相同的结构键 只有name键是硬编码的,但是,如果您决定添加其他非字符串的键,您也必须调整func 为了便于阅读,可以将其拆分 不确定lambdas的性能
这可能有助于itertools.groupby-仅此而已这可能有助于itertools.groupby-仅此而已