Pythonには2つのイテレータブルがありますが、それをペアで見ていきたいと思います。
foo = (1, 2, 3)
bar = (4, 5, 6)
for (f, b) in some_iterator(foo, bar):
print "f: ", f, "; b: ", b
という結果になるはずです。
f: 1; b: 4
f: 2; b: 5
f: 3; b: 6
*1つの方法は、インデックスを反復することです。
for i in xrange(len(foo)):
print "f: ", foo[i], "; b: ", b[i]
しかし、これは私にはやや不自然に思えます。もっと良い方法はありますか?
for f, b in zip(foo, bar):
print(f, b)
zip
は foo
または bar
の短い方が停止すると停止します。
Python 3**では、 zip
は Python2 の itertools.izip
のようにタプルのイテレータを返します。 タプルのリストを取得するには
タプルのリストを得るには、list(zip(foo, bar))
を使います。そして、両方のイテレータがなくなるまで zip を実行するには
また、両方のイテレータがなくなるまで zip を実行するには、次のようにします。
itertools.zip_longestを使用します。
Python 2**では、zip
はタプルのリストを返します。これは foo
と bar
が巨大でない場合には良いことです。両者が巨大な場合、 zip(foo,bar)
を形成することは不必要に巨大な一時変数であり
一時的な変数であり、 itertools.izip
や itertools.izip_
で置き換える必要があります。
これはリストではなくイテレータを返します。
import itertools
for f,b in itertools.izip(foo,bar):
print(f,b)
for f,b in itertools.izip_longest(foo,bar):
print(f,b)
izip
は foo
または bar
のどちらかが枯渇したときに停止します。
izip_longest
は foo
と bar
の両方が使い果たされたときに停止します。
短い方のイテレータを使い切ると、izip_longest
はそのイテレータに対応する位置に None
を持つタプルを生成します。必要に応じて、None
以外の別のfillvalue
を設定することもできます。詳しい話]1はこちらをご覧ください。
また、zip
とそのzip
的なものは、任意の数のイテレートを引数として受け入れることができることに注意してください。たとえば、以下のようになります。
for num, cheese, color in zip([1,2,3], ['manchego', 'stilton', 'brie'],
['red', 'blue', 'green']):
print('{} {} {}'.format(num, color, cheese))
プリント
1 red manchego
2 blue stilton
3 green brie