按特定键对列表中的字典项进行分组

Group dictionary items in a list by their specific keys

我有这个示例列表:

my_list = [
    {
        'data': {
            'color': 'white'
        },
        'name': 'item1'
    },
    {
        'data': {
            'color': 'white',
            'property': 'value1'
        },
        'name': 'item2'
    },
    {
        'data': {
            'color': 'white',
            'property': 'value1'
        },
        'name': 'item3'
    },
    {
        'data': {
            'color': 'black',
            'property': 'value1'
        },
        'name': 'item4'
    },
    {
        'data': {
            'color': 'white',
            'property': 'value1',
            'custom': 'valueA'
        },
        'name': 'item5'
    },
    {
        'data': {
            'color': 'white'
        },
        'name': 'item6'
    },
]

我想将字典项目的名称值与共享相同 'data' 值的项目的其他名称值分组。

所以我想为这个特定的例子得到这个结果: result = [('item1', 'item6'), ('item2', 'item3')]

根据要求更新: 我尝试使用 groupby 将它们分开但没有成功:

import itertools
for key, group in itertools.groupby([item["data"] for item in my_list]):
    print("-"*10)
    for data in group:
        print(data)
out = {}
for d in my_list:
    out.setdefault(tuple(d['data'].items()), []).append(d['name'])

out = [v for v in out.values() if len(v) > 1]
print(out)

打印:

[['item1', 'item6'], ['item2', 'item3']]

您可以使用itertools.groupby

from itertools import groupby
keyfunc = lambda x: sorted(zip(x['data'].keys(), x['data'].values()))
ls = sorted(my_list, key = keyfunc)
groups = []
for k, g in groupby(ls, keyfunc):
    groups.append([n['name'] for n in g]) 
>>> groups
[['item4'], ['item1', 'item6'], ['item5'], ['item2', 'item3']]

样本运行:

>>> sorted(map(keyfunc, my_list))
[[('color', 'black'), ('property', 'value1')], 
[('color', 'white')], 
[('color', 'white')], 
[('color', 'white'), ('custom', 'valueA'), ('property', 'value1')], 
[('color', 'white'), ('property', 'value1')], 
[('color', 'white'), ('property', 'value1')]]

>>> ls
[{'data': {'color': 'black', 'property': 'value1'}, 'name': 'item4'},
 {'data': {'color': 'white'}, 'name': 'item1'}, 
 {'data': {'color': 'white'}, 'name': 'item6'}, 
 {'data': {'color': 'white', 'property': 'value1', 'custom': 'valueA'}, 'name': 'item5'}, 
 {'data': {'color': 'white', 'property': 'value1'}, 'name': 'item2'},
 {'data': {'color': 'white', 'property': 'value1'}, 'name': 'item3'}]

备注:itertools.groupby中的组只允许包含一个项目。你可以用:

>>> [n for n in groups if len(n) > 1]
[['item1', 'item6'], ['item2', 'item3']]