我有一个看起来像这样的元组列表:
lst = [(0, 0), (2, 3), (4, 3), (5, 1)]
累积第一个和第二个元组元素之和的最佳方法是什么?使用上面的示例,我正在寻找生成此列表的最佳方法:
new_lst = [(0, 0), (2, 3), (6, 6), (11, 7)]
我正在寻找 Python 2.6 中的解决方案
我有一个看起来像这样的元组列表:
lst = [(0, 0), (2, 3), (4, 3), (5, 1)]
累积第一个和第二个元组元素之和的最佳方法是什么?使用上面的示例,我正在寻找生成此列表的最佳方法:
new_lst = [(0, 0), (2, 3), (6, 6), (11, 7)]
我正在寻找 Python 2.6 中的解决方案
我认为最好的解决方案是itertools.accumulate()
累积值,并zip()
用来拆分列并将它们合并回来。这意味着生成器只处理单个列,并使该方法完全可扩展。
>>> from itertools import accumulate
>>> lst = [(0, 0), (2, 3), (4, 3), (5, 1)]
>>> list(zip(*map(accumulate, zip(*lst))))
[(0, 0), (2, 3), (6, 6), (11, 7)]
我们zip()
用来取列,然后应用itertools.accumulate()
到每一列,然后zip()
用来将它们合并回原始格式。
此方法适用于任何可迭代的,而不仅仅是序列,并且应该相对有效。
在 3.2 之前,accumulate 可以定义为:
def accumulate(iterator):
total = 0
for item in iterator:
total += item
yield total
(文档页面提供了更通用的实现,但对于这个用例,我们可以使用这个简单的实现)。
这个生成器怎么样:
def accumulate_tuples(iterable):
accum_a = accum_b = 0
for a, b in iterable:
accum_a += a
accum_b += b
yield accum_a, accum_b
如果您需要列表,只需调用list(accumulate_tuples(your_list))
.
这是一个适用于任意长度元组的版本:
def accumulate_tuples(iterable):
it = iter(iterable):
accum = next(it) # initialize with the first value
yield accum
for val in it: # iterate over the rest of the values
accum = tuple(a+b for a, b in zip(accum, val))
yield accum
这适用于任何长度的tuple
s 或其他iterable
s。
from collections import defaultdict
def accumulate(lst):
sums = defaultdict(int)
for item in lst:
for index, subitem in enumerate(item):
sums[index] += subitem
yield [sums[index] for index in xrange(len(sums))]
print [tuple(x) for x in accumulate([(0, 0), (2, 3), (4, 3), (5, 1)])]
在 Python 2.7+ 中,您将使用 aCounter
而不是defaultdict(int)
.
>> reduce(lambda x,y: (x[0] + y[0], x[1] + y[1]), lst)
(11, 7)
编辑。我可以看到你更新的问题。要获取运行列表,您可以执行以下操作:
>> [reduce(lambda x,y: (x[0]+y[0], x[1]+y[1]), lst[:i]) for i in range(1,len(lst)+1)]
[(0, 0), (2, 3), (6, 6), (11, 7)]
不是超级高效,但至少它可以工作并且做你想要的:)
这是一种非常糟糕的方法(就性能而言),因为list.append
它很昂贵,但它确实有效。
last = lst[0]
new_list = [last]
for t in lst[1:]:
last += t
new_list.append(last)
lst = [(0, 0), (2, 3), (4, 3), (5, 1)]
lst2 = [lst[0]]
for idx in range(1, len(lst)):
newItem = [0,0]
for idx2 in range(0, idx + 1):
newItem[0] = newItem[0] + lst[idx2][0]
newItem[1] = newItem[1] + lst[idx2][1]
lst2.append(newItem)
print(lst2)
简单方法:
>> x = [(0, 0), (2, 3), (4, 3), (5, 1)]
>>> [(sum(a for a,b in x[:t] ),sum(b for a,b in x[:t])) for t in range(1,len(x)+1)]
[(0, 0), (2, 3), (6, 6), (11, 7)]
将我的代码更改为更简洁的版本:
lst = [(0, 0), (2, 3), (4, 3), (5, 1)]
def accumulate(the_list):
the_item = iter(the_list)
accumulator = next(the_item)
while True:
yield accumulator
accumulator = tuple(x+y for (x,y) in zip (accumulator, next(the_item)))
new_lst = list(accumulate(lst))
您可以使用以下功能
>>> def my_accumulate(lst):
new_lst = [lst[0]]
for x, y in lst[1:]:
new_lst.append((new_lst[-1][0]+x, new_lst[-1][1]+y))
return new_lst
>>> lst = [(0, 0), (2, 3), (4, 3), (5, 1)]
>>> my_accumulate(lst)
[(0, 0), (2, 3), (6, 6), (11, 7)]