2

将两个或多个元组的值相加以产生每个“列”的总数的最 Pythonic 方式是什么?

例如:

>>> a = (10, 20)
>>> b = (40, 50)
>>> c = (1, 3)
>>> ???
(51, 73)

到目前为止,我已经考虑了以下几点:

def sumtuples(*tuples):
    return (sum(v1 for v1,_ in tuples), sum(v2 for _,v2 in tuples))

>>> print sumtuples(a, b, c)
(51, 73)

我敢肯定这远非理想——如何改进?

4

5 回答 5

6

我想你可以使用reduce,尽管这是否是 pythonic ..

In [13]: reduce(lambda s, t: (s[0]+t[0], s[1]+t[1]), [a, b, c], (0, 0))
Out[13]: (51, 73)

map这是使用and的另一种方式zip

In [14]: map(sum, zip(a, b, c))
Out[14]: [51, 73]

或者,如果您将元组集合作为列表传递:

In [15]: tups = [a, b, c]

In [15]: map(sum, zip(*tups))
Out[15]: [51, 73]

并且,使用列表推导而不是map

In [16]: [sum(z) for z in zip(*tups)]
Out[16]: [51, 73]
于 2009-07-15T19:06:07.787 回答
2

既然我们要疯了,

a = (10, 20)
b = (40, 50)
c = (1, 3)

def sumtuples(*tuples):
   return map(sum, zip(*tuples))

sumtuples(a,b,c)
[51, 73]

事实是,几乎每次我发布这些疯狂的解决方案之一时,“天真的”方法似乎都能更快、更易读……

于 2009-07-15T19:11:15.953 回答
1

不是纯 Python,但如果您安装了 SciPy,这是首选方式:

from scipy import array
a = array((10, 20))
b = array((40, 50))
c = array((1, 3))

print tuple(a+b+c)
于 2009-07-15T19:10:47.717 回答
0

这些解决方案都存在以下两个问题之一:

  • 它们只适用于两列;((1,2,3),(2,3,4),(3,4,5)) 不起作用;或者
  • 它们不适用于迭代器,因此生成十亿行不起作用(或浪费大量内存)。

不要以没有得到正确答案为代价陷入“pythonic”流行语。

def sum_columns(it):
    result = []
    for row in it:
        if len(result) <= len(row):
            extend_by = len(row) - len(result)
            result.extend([0] * extend_by)

        for idx, val in enumerate(row):
            result[idx] += val

    return result

a = (1, 20)
b = (4, 50)
c = (0, 30, 3)
print sum_columns([a,b,c])

def generate_rows():
    for i in range(1000):
        yield (i, 1, 2)

lst = generate_rows()
print sum_columns(lst)
于 2009-07-16T00:31:47.707 回答
0

如果您的元组集相对较小,则您的解决方案很好。但是,如果您要处理非常大的数据集,您应该考虑使用 reduce,因为与您的原始解决方案相比,它只会对列表进行一次迭代,后者对元组列表进行两次迭代。

>>> a = (10, 20)
>>> b = (40, 50)
>>> c = (1, 3)
>>> values=[a,b,c]
>>> reduce(lambda x,y: (x[0]+y[0],x[1]+y[1]), values,(0,0))
(51, 73)
于 2009-07-15T19:05:35.743 回答