在dicts列表中合并相同键的值

时间:2015-06-10 12:54:27

标签: python list python-2.7 dictionary

我是python 2.7的新手,尽管在StackOverflow上进行了大量搜索,但无法弄清楚以下内容:

我有一个list dict我想要组合,当密钥相同时,并添加特定值(在示例'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 个答案:

答案 0 :(得分:4)

Same idea as your question before the edit.

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

Construct a temporary dictionary and accumulate values in it

>>> 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}}

Then using list comprehension and dictionary comprehension, reconstruct the list of dictionaries.

>>> [{'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'}]

Create a temporary dictionary where we can accummulate the sum of prices against their ids,

>>> temp = {}
>>> for d in data:
...     temp[d['id1']] = temp.get(d['id1'], 0) + int(d['price'])
... 
>>> temp
{'a': 4, 'b': 5}

Here we try to get the value of d['id1'] from temp and if it is not found, 0 will be returned. We then add the price from the current dictionary and store the result back in the temp against the current id1.

Then reconstruct the list of dictionaries, with list comprehension添加咨询标题和字典理解,就像这样

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

答案 1 :(得分: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'}]

答案 2 :(得分: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':'green'},{'id1':'b','price':25,'color':'red'},{ 'id1':'c','price':2,'color':'blue'},{'id1':'d','price':1,'color':'white'},{'id1 ':'e','price':20,'color':'yellow'}]

答案 3 :(得分:0)

我设法像这样压缩代码:

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}]