回答:
pairwise()
(またはgrouped()
)実装が必要です。
Python 2の場合:
from itertools import izip
def pairwise(iterable):
"s -> (s0, s1), (s2, s3), (s4, s5), ..."
a = iter(iterable)
return izip(a, a)
for x, y in pairwise(l):
print "%d + %d = %d" % (x, y, x + y)
または、より一般的には:
from itertools import izip
def grouped(iterable, n):
"s -> (s0,s1,s2,...sn-1), (sn,sn+1,sn+2,...s2n-1), (s2n,s2n+1,s2n+2,...s3n-1), ..."
return izip(*[iter(iterable)]*n)
for x, y in grouped(l, 2):
print "%d + %d = %d" % (x, y, x + y)
Python 3ではizip
、組み込みzip()
関数に置き換えて、を削除できますimport
。
すべてのクレジットマーティのための彼の答えに私の質問は、私はそれが唯一のリストの上に一回反復し、その過程で不要なリストを作成していないとして、これは非常に効率的であることがわかってきました。
注意:これは、コメントで@lazyrによって指摘されている、Python独自のドキュメントのpairwise
レシピと混同しないでください。itertools
s -> (s0, s1), (s1, s2), (s2, s3), ...
Python 3 でmypyを使用して型チェックを行いたい人のための少しの追加:
from typing import Iterable, Tuple, TypeVar
T = TypeVar("T")
def grouped(iterable: Iterable[T], n=2) -> Iterable[Tuple[T, ...]]:
"""s -> (s0,s1,s2,...sn-1), (sn,sn+1,sn+2,...s2n-1), ..."""
return zip(*[iter(iterable)] * n)
s -> (s0,s1), (s1,s2), (s2, s3), ...
itertools
、同じ名前のレシピ関数と比較して、ペアの数が半分になります。もちろん、あなたの方が高速です...
izip_longest()
代わりに使用できますizip()
。例:list(izip_longest(*[iter([1, 2, 3])]*2, fillvalue=0))
-> [(1, 2), (3, 0)]
。お役に立てれば。
2要素のタプルが必要なので、
data = [1,2,3,4,5,6]
for i,k in zip(data[0::2], data[1::2]):
print str(i), '+', str(k), '=', str(i+k)
どこ:
data[0::2]
要素のサブセットコレクションを作成することを意味します (index % 2 == 0)
zip(x,y)
xコレクションとyコレクションの同じインデックス要素からタプルコレクションを作成します。for i, j, k in zip(data[0::3], data[1::3], data[2::3]):
import
それらの1つではありません。
>>> l = [1,2,3,4,5,6]
>>> zip(l,l[1:])
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
>>> zip(l,l[1:])[::2]
[(1, 2), (3, 4), (5, 6)]
>>> [a+b for a,b in zip(l,l[1:])[::2]]
[3, 7, 11]
>>> ["%d + %d = %d" % (a,b,a+b) for a,b in zip(l,l[1:])[::2]]
['1 + 2 = 3', '3 + 4 = 7', '5 + 6 = 11']
zip
は、zip
添え字付きではないPython 3のオブジェクトを返します。これは、配列(に変換する必要があるlist
、tuple
まず、等)が、「動作していないこと」ストレッチのビットです。
シンプルなソリューション。
l = [1、2、3、4、5、6] for i(0、len(l)、2)の場合: 出力str(l [i])、 '+'、str(l [i + 1])、 '='、str(l [i] + l [i + 1])
((l[i], l[i+1])for i in range(0, len(l), 2))
、ジェネレーターの場合、より長いタプルに簡単に変更できます。
使用zip
するすべての答えは正しいですが、自分で機能を実装すると、コードが読みやすくなります。
def pairwise(it):
it = iter(it)
while True:
try:
yield next(it), next(it)
except StopIteration:
# no more elements in the iterator
return
it = iter(it)
パート性を保証it
実際にイテレータだけではなく、反復可能です。it
すでにイテレータである場合、この行は何もしません。
使用法:
for a, b in pairwise([0, 1, 2, 3, 4, 5]):
print(a + b)
it
は、が反復子のみで反復可能でない場合にも機能します。他のソリューションは、シーケンスに対して2つの独立した反復子を作成する可能性に依存しているようです。
これがよりエレガントな方法になることを願っています。
a = [1,2,3,4,5,6]
zip(a[::2], a[1::2])
[(1, 2), (3, 4), (5, 6)]
パフォーマンスに興味がある場合simple_benchmark
は、ソリューションのパフォーマンスを比較するために(私のライブラリを使用して)小さなベンチマークを実行し、パッケージの1つの関数を含めました。iteration_utilities.grouper
from iteration_utilities import grouper
import matplotlib as mpl
from simple_benchmark import BenchmarkBuilder
bench = BenchmarkBuilder()
@bench.add_function()
def Johnsyweb(l):
def pairwise(iterable):
"s -> (s0, s1), (s2, s3), (s4, s5), ..."
a = iter(iterable)
return zip(a, a)
for x, y in pairwise(l):
pass
@bench.add_function()
def Margus(data):
for i, k in zip(data[0::2], data[1::2]):
pass
@bench.add_function()
def pyanon(l):
list(zip(l,l[1:]))[::2]
@bench.add_function()
def taskinoor(l):
for i in range(0, len(l), 2):
l[i], l[i+1]
@bench.add_function()
def mic_e(it):
def pairwise(it):
it = iter(it)
while True:
try:
yield next(it), next(it)
except StopIteration:
return
for a, b in pairwise(it):
pass
@bench.add_function()
def MSeifert(it):
for item1, item2 in grouper(it, 2):
pass
bench.use_random_lists_as_arguments(sizes=[2**i for i in range(1, 20)])
benchmark_result = bench.run()
mpl.rcParams['figure.figsize'] = (8, 10)
benchmark_result.plot_both(relative_to=MSeifert)
したがって、外部依存関係のない最速のソリューションが必要な場合は、おそらくJohnyswebが提供するアプローチを使用する必要があります(執筆時点では、これが最も支持され、受け入れられている回答です)。
追加の依存関係を気にしない場合、grouper
from iteration_utilities
はおそらく少し速くなります。
一部のアプローチにはいくつかの制限がありますが、ここでは説明していません。
たとえば、いくつかのソリューションはシーケンス(つまり、リスト、文字列など)に対してのみ機能します。たとえば、Margus / pyanon / taskinoorソリューションはインデックスを使用しますが、他のソリューションは反復可能オブジェクト(シーケンスとオブジェクトジェネレータ、イテレータ)に対して機能します。 mic_e / myソリューション。
次に、Jonyswebは2以外のサイズでも機能するソリューションを提供しましたが、他の回答では機能しません(そう、 iteration_utilities.grouper
、要素の数を「グループ」に設定することもできます)。
次に、リスト内の要素の数が奇数である場合にどうなるかについての質問もあります。残りのアイテムは却下されるべきですか?リストのサイズを均一にするためにリストを埋め込む必要がありますか?残りのアイテムは単一として返されますか?他の答えはこの点に直接対処していませんが、私が何も見落とさなかった場合、それらはすべて残りの項目を却下する必要があるというアプローチに従います(ただし、実際には例外が発生します)。
ではgrouper
、あなたは何をしたいかを決めることができます。
>>> from iteration_utilities import grouper
>>> list(grouper([1, 2, 3], 2)) # as single
[(1, 2), (3,)]
>>> list(grouper([1, 2, 3], 2, truncate=True)) # ignored
[(1, 2)]
>>> list(grouper([1, 2, 3], 2, fillvalue=None)) # padded
[(1, 2), (3, None)]
zip
およびiter
コマンドを一緒に使用します。
私はこのソリューションiter
が非常にエレガントであることを見つけます:
it = iter(l)
list(zip(it, it))
# [(1, 2), (3, 4), (5, 6)]
Python 3のzipドキュメントで見つけました。
it = iter(l)
print(*(f'{u} + {v} = {u+v}' for u, v in zip(it, it)), sep='\n')
# 1 + 2 = 3
# 3 + 4 = 7
# 5 + 6 = 11
N
一度に要素に一般化するには:
N = 2
list(zip(*([iter(l)] * N)))
# [(1, 2), (3, 4), (5, 6)]
for (i, k) in zip(l[::2], l[1::2]):
print i, "+", k, "=", i+k
zip(*iterable)
各イテラブルの次の要素を持つタプルを返します。
l[::2]
リストの1番目、3番目、5番目などの要素を返します。最初のコロンは、後ろに数字がないためスライスが最初から始まることを示します。2番目のコロンは、スライスに「ステップ」が必要な場合にのみ必要です。 '(この場合は2)。
l[1::2]
同じことを行いますが、それは第二、第四、第六、などの要素を返しますので、リストの2番目の要素で開始し、元のリストを。
[number::number]
構文がどのように機能するかを説明するための1 。Pythonをあまり使用しない人に役立つ
開梱あり:
l = [1,2,3,4,5,6]
while l:
i, k, *l = l
print(str(i), '+', str(k), '=', str(i+k))
助けになるかもしれない人のために、これは同様の問題の解決策ですが、(相互に排他的なペアではなく)ペアが重複しています。
Python itertoolsドキュメントから:
from itertools import izip
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return izip(a, b)
または、より一般的には:
from itertools import izip
def groupwise(iterable, n=2):
"s -> (s0,s1,...,sn-1), (s1,s2,...,sn), (s2,s3,...,sn+1), ..."
t = tee(iterable, n)
for i in range(1, n):
for j in range(0, i):
next(t[i], None)
return izip(*t)
more_itertoolsパッケージを使用できます。
import more_itertools
lst = range(1, 7)
for i, j in more_itertools.chunked(lst, 2):
print(f'{i} + {j} = {i+j}')
単純化したアプローチ:
[(a[i],a[i+1]) for i in range(0,len(a),2)]
これは、配列がaであり、ペアで反復したい場合に便利です。3つ以上の組み合わせで反復するには、「範囲」ステップコマンドを変更します。次に例を示します。
[(a[i],a[i+1],a[i+2]) for i in range(0,len(a),3)]
(配列の長さとステップが合わない場合は、余分な値を処理する必要があります)
ここではalt_elem
、forループに適合するメソッドを使用できます。
def alt_elem(list, index=2):
for i, elem in enumerate(list, start=1):
if not i % index:
yield tuple(list[i-index:i])
a = range(10)
for index in [2, 3, 4]:
print("With index: {0}".format(index))
for i in alt_elem(a, index):
print(i)
出力:
With index: 2
(0, 1)
(2, 3)
(4, 5)
(6, 7)
(8, 9)
With index: 3
(0, 1, 2)
(3, 4, 5)
(6, 7, 8)
With index: 4
(0, 1, 2, 3)
(4, 5, 6, 7)
注:上記のソリューションは、funcで実行される操作を考慮すると効率的ではない場合があります。