[英]Accumulate items in a list of tuples
我有一个看起来像这样的元组列表:
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之前,累加可以定义为:
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
>> 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)]
效率不是很高,但是至少它可以正常工作并满足您的要求:)
这适用于任何长度的tuple
或其他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+中,您将使用Counter
而不是defaultdict(int)
。
这是一种非常糟糕的方法(就性能而言),因为list.append
昂贵,但是可以工作。
last = lst[0]
new_list = [last]
for t in lst[1:]:
last += t
new_list.append(last)
您可以使用以下功能
>>> 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)]
简单方法:
>> 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)]
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)
将我的代码更改为简短版本:
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))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.