合并字典列表中相同键的值

6

我是相对新手的Python 2.7程序员,尽管在StackOverflow上进行了广泛的搜索,但仍然无法弄清以下内容:

我有一个包含一组dictlist,希望在键相同时将它们组合起来,并添加特定值(在示例中为'price')。

输入:

[{'id1': 'a', 'price': '2', 'color': 'green'}, {'id1': 'b', 'price': '5', 'color': 'red'}, {'id1': 'a', 'price': '2', 'color': 'green'}] 

预期结果:

[{'id1': 'a', 'price': '4', 'color': 'green'}, {'id1': 'b', 'price': '5', 'color': 'red'}]
4个回答

4

和你之前编辑前的问题一样的想法。

>>> data = [{'id1': 'a', 'price': '2', 'color': 'green'},
...         {'id1': 'b', 'price': '5', 'color': 'red'},
...         {'id1': 'a', 'price': '2', 'color': 'green'}]

构建一个临时字典并在其中累加值。
>>> temp = {}
>>> for d in data:
...     if d['id1'] not in temp:
...         temp[d['id1']] = {}
...     temp_d = temp[d['id1']]
...     temp_d['price'] = temp_d.get('price', 0) + int(d['price'])
...     temp_d.setdefault('colors', set()).add(d['color'])
... 
>>> temp
{'a': {'colors': {'green'}, 'price': 4}, 'b': {'colors': {'red'}, 'price': 5}}

然后使用列表推导和字典推导,重构字典列表。
>>> [{'id1': k, 'price': v['price'], 'colors': v['colors']} for k, v in temp.items()]
[{'id1': 'a', 'colors': {'green'}, 'price': 4}, {'id1': 'b', 'colors': {'red'}, 'price': 5}]

>>> data = [{'id1': 'a', 'price': '2'}, {'id1': 'b', 'price': '5'},
...         {'id1': 'a', 'price': '2'}]

创建一个临时词典,我们可以累加价格与其ID的总和。
>>> temp = {}
>>> for d in data:
...     temp[d['id1']] = temp.get(d['id1'], 0) + int(d['price'])
... 
>>> temp
{'a': 4, 'b': 5}

这里我们尝试从temp中获取d['id1']的值,如果没有找到,则返回0。然后我们将当前字典中的price添加,并将结果存储回temp中对应的id1。

然后使用列表推导式和字典推导式重新构建字典列表,如下所示:

>>> [{'id1': k, 'price': temp[k]} for k in temp]
[{'price': 4, 'id1': 'a'}, {'price': 5, 'id1': 'b'}]

非常好。唯一的问题是第一个字典实际上有另一个值,颜色,在其中一个出现中 {'id1': 'a', 'price': '2', 'color': 'red'}。我如何在最终字典中保留它? - DauleDK
@DauleDK 给定的 id1 在所有字典中颜色都相同吗?例如,如果 id1a,那么颜色是否始终为 green - thefourtheye
不一定,也许可以将这些值连接起来吗? - DauleDK
@DauleDK 嗯,你可以把它变成一组颜色,对吧?记住:集合不会保留重复的值。 - thefourtheye
如果值永远不会改变,答案会是什么样子呢?(我猜这会更简单吧?) - DauleDK

1
我已经成功将代码压缩成这样:

import itertools as it
from operator import itemgetter

grupos = it.groupby(sorted(data, key=itemgetter('id1')), key=itemgetter('id1'))
res = [{'id1': v, 'price': sum(int(dicc['price']) for dicc in diccs) } for v, diccs in 
grupos]
print(res)

输出结果为:
[{'id1': 'a', 'price': 4}, {'id1': 'b', 'price': 25}, {'id1': 'c', 'price': 2}, {'id1': 'd', 'price': 1}, {'id1': 'e', 'price': 20}]

0

这不像 @thefourtheye 那么好,但对我来说似乎可以工作:

di = [{'id1': 'a', 'price': '2', 'color': 'green'}, {'id1': 'b', 'price': '5', 'color': 'red'}, {'id1': 'a', 'price': '2', 'color': 'green'}] 

# Make a dict to hold new values!
newvals = {}

for d in di:
    for key, value in d.iteritems():
        if value.isdigit():
            if value in newvals:
                newvals[value] += int(value)
            else:
                newvals[value] = int(value)
        else:
            if value not in newvals:
                newvals[value] = value

for d in di:
    for nkey, nvalue in d.iteritems():
        d[nkey] = newvals[nvalue]

# Make a unique list of dicts
print {v['id1']:v for v in di}.values()

>>>[{'color': 'green', 'price': 4, 'id1': 'a'}, {'color': 'red', 'price': 5, 'id1': 'b'}]

0
这对我有效:
import collections 
from functools import reduce

data = [{'id1': 'a', 'price': '2', 'color': 'green'},
        {'id1': 'b', 'price': '5', 'color': 'red'},
        {'id1': 'a', 'price': '2', 'color': 'green'},
        {'id1': 'c', 'price': '2', 'color': 'blue'},
        {'id1': 'b', 'price': '5', 'color': 'red'},
        {'id1': 'b', 'price': '5', 'color': 'red'},
        {'id1': 'd', 'price': '1', 'color': 'white'},
        {'id1': 'b', 'price': '10', 'color': 'red'},
        {'id1': 'd', 'price': '20', 'color': 'yellow'}
        ]

valores = [list(item.values()) for item in data]
valores=[[item[0],int(item[1]),item[2]] for item in valores]

dicc = collections.defaultdict(list)
for item in valores:
    dicc[item[0]].append(item[1])
res=list(dicc.items())
res_def=[(t[0],sum(t[1])) for t in res]

colors=[dicc['color'] for dicc in data for item in res_def if item[0] == dicc['id1'] ]          
colors_unicos=reduce(lambda l, x: l.append(x) or l if x not in l else l, colors, [])
for lista in res_def:
    lista.append(colors_unicos.pop(0))

data_resultado=[{'id1':lista[0],'price':lista[1],'color':lista[2]}for lista in res_def]

输出结果为: [{'id1': 'a', 'price': 4, 'color': '绿色'}, {'id1': 'b', 'price': 25, 'color': '红色'}, {'id1': 'c', 'price': 2, 'color': '蓝色'}, {'id1': 'd', 'price': 1, 'color': '白色'}, {'id1': 'e', 'price': 20, 'color': '黄色'}]


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接