字典如何为相同的键添加值

5

我有一个字典列表:

[{'name':'Jay', 'value':'1'},{'name':'roc', 'value':'9'},{'name':'Jay', 'value':'7'},{'name':'roc', 'value':'2'}]

我希望它是:

[{'name':'Jay', 'value':'8'},{'name':'roc', 'value':'11'}]

我尝试过循环,但无法找到可以这样做的示例。任何提示或想法将不胜感激。

7个回答

6
你可以使用一个 defaultdict:
lst = [{'name':'Jay', 'value':'1'},{'name':'roc', 'value':'9'},{'name':'Jay', 'value':'7'},{'name':'roc', 'value':'2'}]

1)为每个姓名求和:

from collections import defaultdict    
result = defaultdict(int)

for d in lst:
    result[d['name']] += int(d['value'])

2) 将名称-值对转换为字典列表:

[{'name': name, 'value': value} for name, value in result.items()]
# [{'name': 'roc', 'value': 11}, {'name': 'Jay', 'value': 8}]

如果您希望将值作为字符串类型输出,可以按照@Kevin的注释所述执行:

[{'name': name, 'value': str(value)} for name, value in result.items()]
​# [{'name': 'roc', 'value': '11'}, {'name': 'Jay', 'value': '8'}]

1
不错的解决方案。根据 OP 是否想要与原始字典的类型匹配,最终表达式中可能需要改为 'value': str(value) - Kevin
是的,我同意@Kevin的观点,我会将它改为str。谢谢,它起作用了,由于时间限制,我很快就会接受答案 :) - J. Doe
1
collections.Counter 也可以是一个不错的替代选择。 - Jean-François Fabre
@Jean-FrançoisFabre确实。您可以回答以展示它的工作原理吗? - Psidom
1
@Psidom 如果你坚持的话 :) 就非常类似于你的。 - Jean-François Fabre

3

这是应用 itertools.groupby 的一个很好的例子。

from itertools import groupby
from operator import itemgetter

orig = [{'name':'Jay', 'value':'1'},
        {'name':'roc', 'value':'9'},
        {'name':'Jay', 'value':'7'},
        {'name':'roc', 'value':'2'}]

get_name = itemgetter('name')
result = [{'name': name, 'value': str(sum(int(d['value']) for d in dicts))}
           for name, dicts in groupby(sorted(orig, key=get_name), key=get_name)]

分解如下:

  1. get_name 是一个函数,给定一个字典,返回其"名称"键的值。即,get_name = lambda x: x['name']

  2. sorted 返回按"名称"键的值排序后的字典列表。

  3. groupby 返回迭代器(名称, 字典),其中字典是具有相同"名称"键值的字典的列表(好吧,是生成器)。(仅对具有相同键值的连续项进行分组,因此需要在上一步中对列表进行排序。)

  4. 结果是一个新字典列表,使用给定的名称和所有相关"value"元素的总和


1
类似于Psidom的回答,但使用 collections.Counter,这是累积整数值的完美选择。
import collections

d =[{'name':'Jay', 'value':'1'},{'name':'roc', 'value':'9'},{'name':'Jay', 'value':'7'},{'name':'roc', 'value':'2'}]

c = collections.Counter()
for sd in d:
    c[sd["name"]] += int(sd["value"])

然后,如果需要的话,您需要重建字典,将其转换回字符串。
print([{"name":n,"value":str(v)} for n,v in c.items()])

结果:

[{'name': 'Jay', 'value': '8'}, {'name': 'roc', 'value': '11'}]

你最好使用defaultdict,因为你所做的只是将defaultdict(int)替换为Counter。你没有利用Counter的主要优势,即在不显式迭代序列的情况下对相关元素进行计数。 - chepner
@chepner 你是对的。在这种情况下,Counter 就不那么有趣了。 - Jean-François Fabre

0
为了完整起见,没有使用 collections.defaultdict:

data = [{'name': 'Jay', 'value': '1'}, {'name': 'roc', 'value': '9'},
        {'name': 'Jay', 'value': '7'}, {'name': 'roc', 'value': '2'}]

result = {}
# concetrate
for element in data:
    result[element["name"]] = result.get(element["name"], 0) + int(element["value"])
# unpack
result = [{"name": element, "value": result[element]} for element in result]
# optionally, you can loop through result.items()
# you can, also, turn back result[elements] to str if needed

print(result)
# prints: [{'name': 'Jay', 'value': 8}, {'name': 'roc', 'value': 11}]

0

使用 itertools 模块中的 groupby 可以解决您的问题:

from itertools import groupby

a = [{'name':'Jay', 'value':'1'},{'name':'roc', 'value':'9'},{'name':'Jay', 'value':'7'},{'name':'roc', 'value':'2'}]
final = []
for k,v in groupby(sorted(a, key= lambda x: x["name"]), lambda x: x["name"]):
    final.append({"name": k, "value": str(sum(int(j["value"]) for j in list(v)))})

print(final)

输出:

[{'name': 'Jay', 'value': '8'}, {'name': 'roc', 'value': '11'}]

0

这里有另一种使用pandas的方法

names = [{'name':'Jay', 'value':'1'},{'name':'roc', 'value':'9'},{'name':'Jay', 'value':'7'},
         {'name':'roc', 'value':'2'}]

df = pd.DataFrame(names)
df['value'] = df['value'].astype(int)
group = df.groupby('name')['value'].sum().to_dict()
result = [{'name': name, 'value': value} for name, value in group.items()]

输出结果为:

[{'value': 8, 'name': 'Jay'}, {'value': 11, 'name': 'roc'}]

0
ld = [{'name':'Jay', 'value':'1'},{'name':'roc', 'value':'9'},{'name':'Jay', 'value':'7'},{'name':'roc', 'value':'2'}]

tempDict = {}
finalList = []


for d in ld:
  name = d['name']
  value = d['value']
  if name not in tempDict:
    tempDict[name] = 0
  tempDict[name] += int(value)

#tempDict => {'Jay': 8, 'roc': 11}

for name,value in tempDict.items():
  finalList.append({'name':name,'value':value})
print(finalList)  

# [{'name': 'Jay', 'value': 8}, {'name': 'roc', 'value': 11}]

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