リスト内の要素の組み合わせを全て知りたい
例えば
['Apple','Orange','Grape']
のリストから
[['Apple'], ['Orange'], ['Grape'], ['Apple', 'Orange'], ['Apple', 'Grape'], ['Orange', 'Grape'], ['Apple', 'Orange', 'Grape']]
という出力を得たいわけです。要素が1つしかない組み合わせもあるし、複数含まれる組み合わせもある。$2^n-1$個の要素をまとめたリストになることはわかるのですが、実際に書こうとしたら躓いてしまった。複雑なネストになりそうじゃないですか。
こういう時に使える標準ライブラリを知りました。
itertools --- 効率的なループ実行のためのイテレータ生成関数
イテレータ | 引数 | 結果 |
---|---|---|
combinations() | p,r | 長さrのタプル列、ソートされた順で重複なし |
例えば、
import itertools
lis = [1,2,3,4]
for pair in itertools.combinations(lis, 2):
print(pair)
上を実行すると以下の結果を得られます。
(1, 2)
(1, 3)
(1, 4)
(2, 3)
(2, 4)
(3, 4)
一応、引数を変えてもう一回試してみましょう。
import itertools
lis = [1,2,3,4]
for team in itertools.combinations(lis, 3):
print(team)
(1, 2, 3)
(1, 2, 4)
(1, 3, 4)
(2, 3, 4)
itertools.combinations() では、このようにリストの要素で、任意の要素数での全ての組み合わせパターンを(タプルで)得られます。
ここで、要素数を1からはじめてリスト長までfor文で回せば、最初に欲しかった答えが得られそうです。
import itertools
lis=['Apple','Orange','Grape']
result = []
for n in range(1,len(lis)+1):
for conb in itertools.combinations(lis, n):
result.append(list(conb)) #タプルをリスト型に変換
print(result)
実行結果
[['Apple'], ['Orange'], ['Grape'], ['Apple', 'Orange'], ['Apple', 'Grape'], ['Orange', 'Grape'], ['Apple', 'Orange', 'Grape']]
『リーダブルコード』でも言及がありますが、普段から標準ライブラリに目を通す癖をつけておくと、良いコードを書けるんだろうなと思いました。
itertoolsについて他のメソッドも含めてまとめているQiitaの良記事がありますので参考に掲載します。
すごいぞitertoolsくん
itertools、more-itertoolsの紹介
便利だと思った標準ライブラリの紹介でした!