合并具有相同键值的单个词典列表

时间:2020-05-29 11:24:39

标签: python

我可以在这里看到许多类似的问题,但是找不到可以帮助我获得所需输出的问题。

我只有一个字典列表,这些字典具有相同的ID,但具有不同的键值对,id喜欢将所有这些键值对连接到一个列表项中,下面是数据示例和所需的输出。

感谢您的帮助

data = [
    {'id': '10', 'animal' : 'cat'},
    {'id': '11', 'animal' : 'dog'},
    {'id': '3', 'animal' : 'pigeon'},
    {'id': '10', 'color' : 'yellow'},
    {'id': '11', 'color' : 'brown'},
    {'id': '3', 'color' : 'grey'},
    {'id': '10', 'type' : 'furry'},
    {'id': '11', 'type' : 'fluffy'},
    {'id': '3', 'type' : 'dirty'},
]

所需的输出

data = [
    {'id': '10', 'animal' : 'cat', 'color' : 'yellow', 'type' : 'furry'},
    {'id': '11', 'animal' : 'dog', 'color' : 'brown', 'type' : 'fluffy'},
    {'id': '3', 'animal' : 'pigeon', 'color' : 'grey', 'type' : 'dirty'},
]

3 个答案:

答案 0 :(得分:2)

有多种方法可以实现此目的,其中一种是defaultdict

In [1]: data = [
   ...:     {'id': '10', 'animal' : 'cat'},
   ...:     {'id': '11', 'animal' : 'dog'},
   ...:     {'id': '3', 'animal' : 'pigeon'},
   ...:     {'id': '10', 'color' : 'yellow'},
   ...:     {'id': '11', 'color' : 'brown'},
   ...:     {'id': '3', 'color' : 'grey'},
   ...:     {'id': '10', 'type' : 'furry'},
   ...:     {'id': '11', 'type' : 'fluffy'},
   ...:     {'id': '3', 'type' : 'dirty'},
   ...: ]

In [2]: from collections import defaultdict
   ...: ids = defaultdict(dict)
   ...: for d in data:
   ...:     ids[d["id"]].update(d)
   ...:


In [6]: list(ids.values())
Out[6]:
[{'id': '10', 'animal': 'cat', 'color': 'yellow', 'type': 'furry'},
 {'id': '11', 'animal': 'dog', 'color': 'brown', 'type': 'fluffy'},
 {'id': '3', 'animal': 'pigeon', 'color': 'grey', 'type': 'dirty'}]

答案 1 :(得分:0)

在Python 3.9(ETA 2020年秋季)中,您将能够使用|运算符来合并具有相同dict键的id

from itertools import groupby
from operator import or_, itemgetter
from functools import reduce

# I know *why* groupby doesn't have an option to
# sort your data first, but that doesn't mean I can't
# wish that it could...
def group(data, key):
    "Iterate over groups of dicts considered equal according to key"
    yield from map(itemgetter(1), groupby(sorted(data, key=key), key))

data = [
    {'id': '10', 'animal' : 'cat'},
    {'id': '11', 'animal' : 'dog'},
    {'id': '3', 'animal' : 'pigeon'},
    {'id': '10', 'color' : 'yellow'},
    {'id': '11', 'color' : 'brown'},
    {'id': '3', 'color' : 'grey'},
    {'id': '10', 'type' : 'furry'},
    {'id': '11', 'type' : 'fluffy'},
    {'id': '3', 'type' : 'dirty'},
    ]


# E.g., {'id': 10, 'animal': 'cat'} | {'id': 10, 'color': 'yellow'}
#  == {'id': 10, 'animal': 'cat', 'color': 'yellow'}
data = [reduce(or_, ds) for ds in group(data, itemgetter('id'))]

答案 2 :(得分:0)

您可以使用groupbyChainMap

from itertools import groupby
from collections import ChainMap

id_getter = lambda x: x['id']
gp = groupby(sorted(data, key=id_getter), key=id_getter)
result = [dict(ChainMap(*a)) for _, a in gp]

groupby适用于排序的集合,因此在调用data之前对groupby进行排序
ChainMap用于将词典列表合并到单个词典中