Python元组列表中每个元素的总和

3
我想要将包含元组的列表的每个元素相加。例如,
    >>> list1
    [(0, 1, 2), (3, 4, 5), (6, 7, 8)]
    >>> list2
    [(1, 2, 3), (4, 5, 6), (7, 8, 9)]

答案应该是:
     list3 = [(1,3,5),(7,9,11),(13,15,17)]

请给出你的赞并从以下三个答案中选择一个。 - Matt Alcock
6个回答

8

在这里,zip是您的好帮手。

result = []
for ta, tb in zip(list1, list2):
     t =tuple(a+b for a, b in zip(ta, tb))
     result.append(t)

print result
>> [(1,3,5),(7,9,11),(13,15,17)]

更符合 Python 风格的写法是:
result = [tuple(a+b for a, b in zip(ta, tb)) for ta, tb in zip(list1, list2)]
print result
>> [(1,3,5),(7,9,11),(13,15,17)]

通过这样做,结果可以简单地成为一个生成器:

result = (tuple(a+b for a, b in zip(ta, tb)) for ta, tb in zip(list1, list2))

2
我并不完全认为列表推导式在这种情况下更符合Pythonic的风格,它显然更难以阅读。通过使用timeit比较两种方法,展开的for循环也稍微快了一点(大约5%)。通常来说,列表推导式应该是更优选的,但是嵌套的列表推导式有时会变得非常难以理解。 - Adam Parkin
1
我同意Adam的观点,这段代码不易读懂。我提到更符合Python风格是因为通过改变括号,结果很容易就可以变成生成器。这意味着结果在需要之前不会被分配到内存或迭代。请参见上面的修改... - Matt Alcock

4
>>> list1 = [(0, 1, 2), (3, 4, 5), (6, 7, 8)]
>>> list2 = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]
>>> [tuple(map(sum, zip(*i))) for i in zip(list1, list2)]
[(1, 3, 5), (7, 9, 11), (13, 15, 17)]

这种方法的好处是它适用于任意数量的列表。
>>> list3 = [tuple(map(sum, zip(*i))) for i in zip(list1, list2)]
>>> [tuple(map(sum, zip(*i))) for i in zip(list1, list2, list3)]
[(2, 6, 10), (14, 18, 22), (26, 30, 34)]

如果我的列表是动态的,那么如何计算这种事情。 - DASADIYA CHAITANYA
@DaSaDiYaChaiTAnYa,不确定你的意思。你能举个例子吗? - John La Rooy
好的,没问题。我已经从我的一面解决了这个问题。我的问题是上面的答案使用了两个不同的列表,比如list1和list2,但当列表是动态生成的时,如何解决这种情况呢? - DASADIYA CHAITANYA

3
你可以使用列表推导式,虽然有些别扭:
list3 = [tuple(x + y for x, y in zip(t1, t2))
         for t1, t2 in zip(list1, list2)]

如果您可以接受列表的列表而不是元组的列表,另一种选择是

list3 = [map(operator.add, *t) for t in zip(list1, list2)]

2
有趣的是,另一个发帖者认为“笨拙”的代码更具Python风格。 - georg
1
如果OP只有11个声望值,我也会觉得很尴尬!我也这么想过,参考了谷歌的Python风格指南来帮助澄清。说实话,没什么帮助。 - yurisich
1
有趣的事实:在我的实验中(使用timeit),上面的map()版本比列表推导式快了约50%,但是在Python社区中,map仍然是不受欢迎的函数。 - Adam Parkin
1
@Adam,我不会说这是被反对的,但只有在相对较少的特定情况下,使用map仍然比列表推导更有意义,并且需要花费相当长的时间来学习何时应该使用它。 - John La Rooy
(+1) 如果OP真的需要一个元组,他可以在imap()周围包装tuple() - Rik Poggi
澄清一下:我并不是说 map 函数在正式上已经被弃用,但是 Guido 的这篇文章 似乎表明了一定程度的“你可以使用它们,但最好做这个”,这就是我的意思。另外值得一提的是,Python 风格检查器 PyLint 实际上会将对 map 函数的调用标记为警告,进一步表明了某种“也许你应该重新考虑使用它”的氛围。 - Adam Parkin

1
>>> [tuple(sum(pair) for pair in zip(a,b)) for a,b in zip(list1,list2)]
[(1, 3, 5), (7, 9, 11), (13, 15, 17)]

1

编辑:以下内容完全不需要。内置的map函数可以自动将传递给它的多个可迭代对象压缩在一起,因此zip_with(func, iter1, iter2)可以用相同参数的map函数来替换。

map(functools.partial(map, op.add), list1, list2)

此部分不需要

这里有一个代码片段,实现了类似Haskell中的zipWith函数。

def zip_with(func, xs, ys):
    return [func(x, y) for (x, y) in zip(xs, ys)]

In [1]: def zip_with(func, xs, ys):
   ...:         return [func(x, y) for (x, y) in zip(xs, ys)]
   ...: 

In [2]: import operator as op

In [3]: zip_with(op.add, [1,2,3], [4,5,6])
Out[3]: [5, 7, 9]

In [4]: import functools

In [5]: zip_with(functools.partial(zip_with, op.add), list1, list2)
Out[5]: [[1, 3, 5], [7, 9, 11], [13, 15, 17]]

-1
import operator
list3 = [tuple(map(operator.add, list1[i], list2[i]))
 for i in range(len(list1))]

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