Python 词典列表的收集计数器
Python Collections Counter for a List of Dictionaries
我有一个动态增长的数组列表,我想将类似的值加在一起。这是一个例子:
{"something" : [{"one":"200"}, {"three":"400"}, {"one":"100"}, {"two":"800"} ... ]}
我希望能够将列表中的词典加在一起。因此,在这种情况下,对于键 "something",结果将是:
["one":400, "three": 400, "two": 800]
或类似的东西。我熟悉 Python 的收集计数器,但由于 "something" 列表包含字典,它不会工作(除非我遗漏了什么)。字典也是动态创建的,所以没有字典我无法构建列表。例如:
Counter({'b':3, 'c':4, 'd':5, 'b':2})
通常可以,但是一旦我尝试添加一个元素,之前的值就会被覆盖。我注意到其他问题,例如:
Is there any pythonic way to combine two dicts (adding values for keys that appear in both)?
Python count of items in a dictionary of lists
但同样,列表中的对象是字典。
一种方法如下:
from collections import defaultdict
d = {"something" :
[{"one":"200"}, {"three":"400"}, {"one":"100"}, {"two":"800"}]}
dd = defaultdict(list)
# first get and group values from the original data structure
# and change strings to ints
for inner_dict in d['something']:
for k,v in inner_dict.items():
dd[k].append(int(v))
# second. create output dictionary by summing grouped elemetns
# from the first step.
out_dict = {k:sum(v) for k,v in dd.items()}
print(out_dict)
# {'two': 800, 'one': 300, 'three': 400}
这里我没有使用counter,而是defaultdict。这是一个两步走的方法。
我认为这符合您的要求,但我不确定,因为我不知道 "The dict is also being dynamically created, so I can't build the list without the dicts" 是什么意思。仍然:
input = {
"something" : [{"one":"200"}, {"three":"400"}, {"one":"100"}, {"two":"800"}],
"foo" : [{"a" : 100, "b" : 200}, {"a" : 300, "b": 400}],
}
def counterize(x):
return Counter({k : int(v) for k, v in x.iteritems()})
counts = {
k : sum((counterize(x) for x in v), Counter())
for k, v in input.iteritems()
}
结果:
{
'foo': Counter({'b': 600, 'a': 400}),
'something': Counter({'two': 800, 'three': 400, 'one': 300})
}
我预计将 sum
与 Counter
一起使用是低效的(就像将 sum
与字符串一起使用一样低效以至于 Guido 禁止它),但我可能是错的。无论如何,如果您遇到性能问题,您可以编写一个函数来创建 Counter
并在其上重复调用 +=
或 update
:
def makeints(x):
return {k : int(v) for k, v in x.iteritems()}
def total(seq):
result = Counter()
for s in seq:
result.update(s)
return result
counts = {k : total(makeints(x) for x in v) for k, v in input.iteritems()}
我有一个动态增长的数组列表,我想将类似的值加在一起。这是一个例子:
{"something" : [{"one":"200"}, {"three":"400"}, {"one":"100"}, {"two":"800"} ... ]}
我希望能够将列表中的词典加在一起。因此,在这种情况下,对于键 "something",结果将是:
["one":400, "three": 400, "two": 800]
或类似的东西。我熟悉 Python 的收集计数器,但由于 "something" 列表包含字典,它不会工作(除非我遗漏了什么)。字典也是动态创建的,所以没有字典我无法构建列表。例如:
Counter({'b':3, 'c':4, 'd':5, 'b':2})
通常可以,但是一旦我尝试添加一个元素,之前的值就会被覆盖。我注意到其他问题,例如:
Is there any pythonic way to combine two dicts (adding values for keys that appear in both)?
Python count of items in a dictionary of lists
但同样,列表中的对象是字典。
一种方法如下:
from collections import defaultdict
d = {"something" :
[{"one":"200"}, {"three":"400"}, {"one":"100"}, {"two":"800"}]}
dd = defaultdict(list)
# first get and group values from the original data structure
# and change strings to ints
for inner_dict in d['something']:
for k,v in inner_dict.items():
dd[k].append(int(v))
# second. create output dictionary by summing grouped elemetns
# from the first step.
out_dict = {k:sum(v) for k,v in dd.items()}
print(out_dict)
# {'two': 800, 'one': 300, 'three': 400}
这里我没有使用counter,而是defaultdict。这是一个两步走的方法。
我认为这符合您的要求,但我不确定,因为我不知道 "The dict is also being dynamically created, so I can't build the list without the dicts" 是什么意思。仍然:
input = {
"something" : [{"one":"200"}, {"three":"400"}, {"one":"100"}, {"two":"800"}],
"foo" : [{"a" : 100, "b" : 200}, {"a" : 300, "b": 400}],
}
def counterize(x):
return Counter({k : int(v) for k, v in x.iteritems()})
counts = {
k : sum((counterize(x) for x in v), Counter())
for k, v in input.iteritems()
}
结果:
{
'foo': Counter({'b': 600, 'a': 400}),
'something': Counter({'two': 800, 'three': 400, 'one': 300})
}
我预计将 sum
与 Counter
一起使用是低效的(就像将 sum
与字符串一起使用一样低效以至于 Guido 禁止它),但我可能是错的。无论如何,如果您遇到性能问题,您可以编写一个函数来创建 Counter
并在其上重复调用 +=
或 update
:
def makeints(x):
return {k : int(v) for k, v in x.iteritems()}
def total(seq):
result = Counter()
for s in seq:
result.update(s)
return result
counts = {k : total(makeints(x) for x in v) for k, v in input.iteritems()}