次のようなタプルのリストがあります。
lst = [(0, 0), (2, 3), (4, 3), (5, 1)]
最初と 2 番目のタプル要素の合計を累積する最良の方法は何ですか? 上記の例を使用して、このリストを作成する最良の方法を探しています。
new_lst = [(0, 0), (2, 3), (6, 6), (11, 7)]
Python 2.6 で解決策を探しています
次のようなタプルのリストがあります。
lst = [(0, 0), (2, 3), (4, 3), (5, 1)]
最初と 2 番目のタプル要素の合計を累積する最良の方法は何ですか? 上記の例を使用して、このリストを作成する最良の方法を探しています。
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+では、 のCounter
代わりにa を使用します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)
次の機能を使用できます
>>> 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)]
私のコードをより簡潔なバージョンに変更しました:
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))
簡単な方法:
>> 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)]