简体   繁体   English

使用元组的嵌套列表创建Python defaultdict

[英]Creating Python defaultdict using nested list of tuples

The scenario is that I have a 2-D list. 场景是我有一个二维列表。 Each item of the inner list is tuple (key, value pair). 内部列表的每一项都是元组(键,值对)。 The key might repeat in the list. 该键可能会在列表中重复。 I want to create a default-dict on the fly, in such a way that finally, the dictionary stores the key, and the cumulative sum of all the values of that key from the 2-D list. 我想即时创建一个默认字典,以使字典最终存储密钥以及2-D列表中该密钥的所有值的累加和。

To put the code : 把代码:

listOfItems = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]
finalDict = defaultdict(int)
for eachItem in listOfItems:
    for key, val in eachItem:
        finalDict[key] += val
print(finalDict)

This is giving me what I want : defaultdict(<class 'int'>, {'a': 7, 'b': 5, 'c': 0, 'd': 5}) but I am looking for a more 'Pythonic' way using comprehensions. 这给了我我想要的东西: defaultdict(<class 'int'>, {'a': 7, 'b': 5, 'c': 0, 'd': 5})但我正在寻找更多使用理解的“ Pythonic”方式。 So I tried the below : 所以我尝试了以下方法:

finalDict = defaultdict(int)
finalDict = {key : finalDict[key]+val for eachItem in listOfItems for key, val in eachItem}
print(finalDict)

But the output is : {'a': 6, 'b': 2, 'c': 0, 'd': 5} What is it that I am doing wrong? 但是输出是: {'a': 6, 'b': 2, 'c': 0, 'd': 5}我做错了什么? Or is it that when using comprehension the Dictionary is not created and modified on the fly? 还是在使用理解时不立即创建和修改字典?

Yes a comprehension can't be updated on-the-fly. 是的,理解不能即时更新。 Anyway, this task might be better suited to collections.Counter() with .update() calls: 无论如何,此任务可能更适合于具有.update()调用的collections.Counter()

>>> from collections import Counter
>>> c = Counter()
>>> for eachItem in listOfItems:
...     c.update(dict(eachItem))
... 
>>> c
Counter({'a': 7, 'b': 5, 'd': 5, 'c': 0})

Simple solution without using additional modules: 不使用其他模块的简单解决方案:

inp_list = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]

l = [item for sublist in inp_list for item in sublist] # flatten the list

sums = [(key, sum([b for (a,b) in l if a == key])) for key in dict(l)]

print(sums)

This is because you do not assign any value to your finalDict inside your dict in comprehension. 这是因为您不会在dict内将任何值分配给finalDict。

In your dict in comprehension you are literally changing the type of finalDict 在理解的字典中,您实际上是在更改finalDict的类型

As far as I know you cannot assign value to your dict inside a dict in comprehension. 据我所知,您无法在理解的字典中为字典分配值。

Here is a way to get the dictionnary you want 这是获取所需字典的一种方法

from functools import reduce

listOfItems = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]

list_dict = [{key: val} for eachItem in listOfItems for key, val in eachItem]

def sum_dict(x, y):
    return {k: x.get(k, 0) + y.get(k, 0) for k in set(x) | set(y)}
print(reduce(sum_dict, list_dict))

trying to use python's built-in methods instead of coding the functionality myself: 尝试使用python的内置方法代替自己编写功能:

The long and explained solution 详细的解决方案

from itertools import chain, groupby
from operator import itemgetter

listOfItems = [[('a', 1), ('b', 3)], [('a', 6)], [('c', 0), ('d', 5), ('b', 2)]]

# just flat the list of lists into 1 list..
flatten_list = chain(*listOfItems)

# get all elements grouped by the key, e.g 'a', 'b' etc..
first = itemgetter(0)
groupedByKey = groupby(sorted(flatten_list, key=first), key=first))

#sum
summed_by_key = ((k, sum(item[1] for item in tups_to_sum)) for k, tups_to_sum in groupedByKey)

# create a dict
d = dict(summed_by_key)

print(d) # {'a': 7, 'b': 5, 'c': 0, 'd': 5}

~one line solution 〜一线解决方案

from itertools import chain, groupby
from operator import itemgetter

first = itemgetter(0)
d = dict((k, sum(item[1] for item in tups_to_sum)) for k, tups_to_sum in groupby(sorted(chain(*listOfItems), key=first), key=first))

print(d) # {'a': 7, 'b': 5, 'c': 0, 'd': 5}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM