如何使用reduce函数在python中创建字数统计输出?

时间:2017-04-02 19:15:46

标签: python list tuples reduce word-count

我有以下元组列表:[('a', 1), ('a', 1), ('b', 1), ('c',1), ('a', 1), ('c', 1)]

我想知道我是否可以利用python的reduce函数来聚合它们并产生以下输出:[('a', 3), ('b', 1), ('c', 2)]

或者,如果还有其他方法,我也想知道(循环很好)

3 个答案:

答案 0 :(得分:3)

使用reduce似乎很难实现,因为如果你“减少”的两个元组都不具有相同的字母,则无法计算结果。如何将('a',1)('b',1)降低到一些可行的结果?

我能做的最好的事情是l = functools.reduce(lambda x,y : (x[0],x[1]+y[1]) if x[0]==y[0] else x+y,sorted(l))

它让我('a', 3, 'b', 1, 'c', 1, 'c', 1)。所以它适用于第一个元素,但是需要不止一个传递来完成其他元素(重新创建元组并创建另一个类似reduce,好吧,至少可以说效率不高!)。

无论如何,这里有2种工作方式

首先,使用collections.Counter计数相同类型的元素:

l = [('a', 1), ('a', 1), ('b', 1), ('c',1), ('a', 1), ('c', 1)]

import collections

c = collections.Counter()
for a,i in l:
    c[a] += i

我们不能使用listcomp,因为每个元素都有一个权重(即使这里是1)

结果:字典:Counter({'a': 3, 'c': 2, 'b': 1})

第二个选项:在排序列表上使用itertools.groupby,按名称/字母分组,并对带有相同字母的整数执行求和:

print ([(k,sum(e for _,e in v)) for k,v in itertools.groupby(sorted(l),key=lambda x : x[0])])

结果:

[('a', 3), ('b', 1), ('c', 2)]

答案 1 :(得分:1)

使用defaultdict子类和sum函数的替代方法:

import collections

l = [('a', 1), ('a', 1), ('b', 1), ('c',1), ('a', 1), ('c', 1)]
d = collections.defaultdict(list)
for t in l:
    d[t[0]].append(t[1])

result = [(k,sum(v)) for k,v in d.items()]
print(result)

输出:

[('b', 1), ('a', 3), ('c', 2)]

答案 2 :(得分:0)

另一种方法是创建自定义的reduce函数。
例如:
l = [('a',1),('a',1),('b',1),('c',1),('a',1),('c',1) ]

def myreduce(func , seq):
    output_dict = {}
    for k,v in seq:
        output_dict[k] = func(output_dict.get(k,0),v)
    return output_dict  

myreduce((lambda sum,value:total + sum),l)

输出:
{'a':3,'b':1,'c':2}

之后,您可以将生成的输出修改为元组列表。