繁体   English   中英

累积元组列表中的项目

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM