はじめに
以前 Array#product で多重ループを回避しよう という Ruby の記事を投稿しました。この記事では Array#product を利用して多重ループを単一ループに変える1方法を紹介しています。最近は個人的に Python に傾倒しているので、この言語ではどう書けるかを探ってみました。
変更前のサンプルコード
python
for year in range(2010, 2013):
for i in range(1, 3):
for char in ('a', 'b', 'c'):
print(year, i, char)
stdout
2010 1 a
2010 1 b
2010 1 c
2010 2 a
2010 2 b
2010 2 c
2011 1 a
2011 1 b
2011 1 c
2011 2 a
2011 2 b
2011 2 c
2012 1 a
2012 1 b
2012 1 c
2012 2 a
2012 2 b
2012 2 c
方法 1: itertools.product() を使う
Ruby の Array#product と同様に Python にも itertools.product() というデカルト積 (直積) を求めるための関数があります。
python
from itertools import product
years = range(2010, 2013)
integers = range(1, 3)
chars = ('a', 'b', 'c')
for year, i, char in product(years, integers, chars):
print(year, i, char)
方法 2: 内包表記を使う
ネストした内包表記も利用できます。
python
years = range(2010, 2013)
integers = range(1, 3)
chars = ('a', 'b', 'c')
combinations = [(year, i, char)
for year in years
for i in integers
for char in chars]
for year, i, char in combinations:
print(year, i, char)
おまけ: Ruby の場合
ruby
years = Array(2010..2012)
integers = Array(1..2)
chars = Array('a'..'c')
years.product(integers, chars) { |year, i, char| puts("#{year} #{i} #{char}") }
参考
-
ジェダイ流・Pythonの内包表記
- ネストした内包表記について参考にしました。
-
あくまで見かけ上の話で、ループ構文によるインデントを複数から 1 つにすることです。内部的なループ回数や計算量が減るわけではありません。 ↩