5

次のようなタプルのリストがあります。

lst = [(0, 0), (2, 3), (4, 3), (5, 1)]

最初と 2 番目のタプル要素の合計を累積する最良の方法は何ですか? 上記の例を使用して、このリストを作成する最良の方法を探しています。

new_lst = [(0, 0), (2, 3), (6, 6), (11, 7)]

Python 2.6 で解決策を探しています

4

9 に答える 9

14

最良の解決策は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

(ドキュメント ページではより一般的な実装が提供されていますが、このユース ケースでは、この単純な実装を使用できます)。

于 2013-05-07T17:49:08.070 に答える
3

このジェネレーターはどうですか:

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
于 2013-05-07T17:48:42.430 に答える
2

これは、任意の長さのtuples またはその他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代わりにa を使用しますdefaultdict(int)

于 2013-05-07T17:49:43.940 に答える
2
>> 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)]

非常に効率的ではありませんが、少なくとも機能し、あなたが望むことをします:)

于 2013-05-07T17:43:12.217 に答える
1

これはlist.appendコストがかかるため (パフォーマンスの点で) 非常に貧弱な方法ですが、機能します。

last = lst[0]
new_list = [last]
for t in lst[1:]:
    last += t
    new_list.append(last)
于 2013-05-07T17:40:55.230 に答える
0
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)
于 2013-05-07T17:48:16.963 に答える
0

次の機能を使用できます

>>> 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)]
于 2013-05-07T17:41:50.397 に答える
0

私のコードをより簡潔なバージョンに変更しました:

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))
于 2013-05-07T17:52:59.697 に答える
0

簡単な方法:

>> 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)]
于 2013-05-07T17:43:17.587 に答える