Pythonの技法:ジェネレータを用いた遅延リストの構築

文:Nick Gibson(Builder AU)  翻訳校正:原井彰弘
2008-01-17 15:00:00
  • このエントリーをはてなブックマークに追加

 これで必要な処理のみを行うバージョンが完成した。このコードは、それ以外の点に関してはすべて先ほどのコードと同様に動作する。実際の使用例を以下に示そう。

>>> comb = xcombination("ABCDE", 3)
>>> comb.next()
['A', 'B', 'C']
>>> comb.next()
['A', 'B', 'D']
>>> list(comb)
[['A', 'B', 'E'], ['A', 'C', 'D'], ['A', 'C', 'E'], ['A', 'D', 'E'], ['B', 'C', 'D'], ['B', 'C', 'E'], ['B', 'D', 'E'], ['C', 'D', 'E']]
>>> comb2 = xcombination("ABCDE",2)
>>> for i in xrange(3):
... print comb2.next()
... ['A', 'B']
['A', 'C']
['A', 'D']

 たとえば最後のコマンドでは、10の異なる文字の組み合わせが存在するものの、実際に生成されたのは3つのみである。つまり、先ほどの一般的な記述方法と比べて、70パーセントの計算時間が節約されたことになる。

 ジェネレータが非常に便利な理由は、多くの場合簡単にリストの内包表記と交換できるからだ。リストの内包表記をジェネレータに置き換えるには、リストの内包表記をくくっているブラケットを括弧に変えるだけでよいのである。リストの内包表記に関する記事で最後に載っていた例を用い、説明を行おう。

>>> guests = ['Chris', 'Brendan', 'Jimmy', 'Mel', 'Mike', 'Jess']
>>> [(seat1, seat2) for seat1 in guests for seat2 in guests if seat1 != seat2]
...

 このコードは以下のように記述できる。

>>> guests = ['Chris', 'Brendan', 'Jimmy', 'Mel', 'Mike', 'Jess']
>>> ((seat1, seat2) for seat1 in guests for seat2 in guests if seat1 != seat2)

 これだけで、ほかのジェネレータと同様に扱うことが可能になるのである。

>>> seating = ((seat1, seat2) for seat1 in guests for seat2 in guests if seat1 != seat2)
>>> for i in xrange(10):
... print seating.next()
...
('Chris', 'Brendan')
('Chris', 'Jimmy')
('Chris', 'Mel')
('Chris', 'Mike')
('Chris', 'Jess')
('Brendan', 'Chris')
('Brendan', 'Jimmy')
('Brendan', 'Mel')
('Brendan', 'Mike')
('Brendan', 'Jess')
このサイトでは、利用状況の把握や広告配信などのために、Cookieなどを使用してアクセスデータを取得・利用しています。 これ以降ページを遷移した場合、Cookieなどの設定や使用に同意したことになります。
Cookieなどの設定や使用の詳細、オプトアウトについては詳細をご覧ください。
[ 閉じる ]