如何在元组列表上使用reduce函数?

8

我有一个元组列表:

  a = [(1, 2), (1, 4), (1, 6)]

我想使用reduce函数来获得这个结果:
  (3, 12)

我尝试了:

  x = reduce(lambda x, y: x+y, a)

但是我遇到了一个错误……我想将每个元组的第一个索引中的所有元素相加,然后再加上第二个元素。

4个回答

13
如果你希望 reduce 的输出是一个元组,则所有中间结果也应该是元组。
a = [(1, 2), (1, 4), (1, 6)]
print reduce(lambda x, y: (x[0] + y[0], x[1] + y[1]), a)

输出

(3, 12)

编辑:如果你希望在列表为空时得到 (0, 0)

a = []
print reduce(lambda x, y: (x[0] + y[0], x[1] + y[1]), [(0, 0)] + a)

输出

(0, 0)

编辑2: Reduce函数的最后一个参数可以使用默认初始化程序进行可选设置。通过使用该初始化程序,代码变为:

a = []
print reduce(lambda x, y: (x[0] + y[0], x[1] + y[1]), a, (0, 0))

如果我有一个空列表,并使用reduce函数,如何让它给我结果(0,0)?目前,它会给我一个“int对象不可索引”的错误提示。 - Kara
我将列表'a'设置为空列表,即a = [],然后我会返回您刚编写的reduce函数。但是,在那之后我会遇到一个错误。 - Kara
2
@Lalala,请现在检查我的答案。 - thefourtheye
reduce 接受可选的 initializer: reduce(lambda x, y: (x[0] + y[0], x[1] + y[1]), a, (0, 0)) - falsetru
@falsetru 我编辑了我的答案并包含了那个。谢谢 :) - thefourtheye

7
>>> a = [(1, 2), (1, 4), (1, 6)]
>>> map(sum, zip(*a))
[3, 12]

更新

根据Raymond Hettinger的说法,zip-star技巧滥用堆栈来昂贵地计算转置。

这里有一个替代方案,不使用列表推导。

>>> a = [(1, 2), (1, 4), (1, 6)]
>>> [sum(item[i] for item in a) for i in range(2)] # 2 == len(a[0])
[3, 12]
>>> a = []
>>> [sum(item[i] for item in a) for i in range(2)] # 2 == len(a[0])
[0, 0]

或者作为元组 tuple(map(sum, zip(*a))) - aIKid
1
虽然看起来很漂亮,但这并不是解决问题的好方法。它的可扩展性不好(zip-star技巧滥用堆栈来昂贵地计算转置,而这并不是解决问题所必需的)。 - Raymond Hettinger
1
@RaymondHettinger,感谢您的评论。我已经根据您的评论更新了答案。 - falsetru

3
你已经很接近了。只需修改代码以首先展开输入元组。添加新值后,将结果重新打包成元组:
>>> a = [(1, 2), (1, 4), (1, 6)]
>>> reduce(lambda (sx, sy), (x, y): (sx+x, sy+y), a)
(3, 12)

0

请尝试这个:

>>> from numpy import asarray
>>> a = asarray([(1, 2), (1, 4), (1, 6)])
>>> reduce(lambda x,y:x+y, a)
array([ 3, 12])

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