今回はPythonで複数のリストから組み合わせを作成する方法をご紹介します。標準ライブラリのitertoolsを使うととても簡単に作成できます。

例えば以下のような、abc の3つの価格帯の商品から1つずつ選んで、福袋の中身の組み合わせをPythonで作成する方法を考えてみます。

# 価格帯「低」
>>>  a = ["USBケーブル", "SDカード", "マウス"]
# 価格帯「中」
>>> b = ["Webカメラ", "USB充電器", "キーボード"]
# 価格帯「高」
>>> c = ["ポータブルHDD", "WiFiルーター"]
本記事の目次

for文を用いて組み合わせを作成する場合

まず単純にfor文だけを使うと以下のようにプログラミングできます。

>>> for i in a:
	for j in b:
		for k in c:
			print((i, j, k))

			
('USBケーブル', 'Webカメラ', 'ポータブルHDD')
('USBケーブル', 'Webカメラ', 'WiFiルーター')
('USBケーブル', 'USB充電器', 'ポータブルHDD')
('USBケーブル', 'USB充電器', 'WiFiルーター')
('USBケーブル', 'キーボード', 'ポータブルHDD')
('USBケーブル', 'キーボード', 'WiFiルーター')
('SDカード', 'Webカメラ', 'ポータブルHDD')
('SDカード', 'Webカメラ', 'WiFiルーター')
('SDカード', 'USB充電器', 'ポータブルHDD')
('SDカード', 'USB充電器', 'WiFiルーター')
('SDカード', 'キーボード', 'ポータブルHDD')
('SDカード', 'キーボード', 'WiFiルーター')
('マウス', 'Webカメラ', 'ポータブルHDD')
('マウス', 'Webカメラ', 'WiFiルーター')
('マウス', 'USB充電器', 'ポータブルHDD')
('マウス', 'USB充電器', 'WiFiルーター')
('マウス', 'キーボード', 'ポータブルHDD')
('マウス', 'キーボード', 'WiFiルーター')

多重にネスト(入れ子)することになるので、とても見づらいです。

itertools標準ライブラリによる組み合わせの作成

次に、標準ライブラリのitertoolsにあるproduct()を利用してみます。

以下のようにfor文は1つで済みます。ここで、product()はfor文で用いると繰り返しデータを返します(イテレータと呼ばれます)。今回は、abcの3つのリストの要素どうしを組み合わせたタプルを返してくれます。

>>> import itertools
>>> for fuku in itertools.product(a,b,c):
	print(fuku)

	
('USBケーブル', 'Webカメラ', 'ポータブルHDD')
('USBケーブル', 'Webカメラ', 'WiFiルーター')
('USBケーブル', 'USB充電器', 'ポータブルHDD')
('USBケーブル', 'USB充電器', 'WiFiルーター')
('USBケーブル', 'キーボード', 'ポータブルHDD')
('USBケーブル', 'キーボード', 'WiFiルーター')
('SDカード', 'Webカメラ', 'ポータブルHDD')
('SDカード', 'Webカメラ', 'WiFiルーター')
('SDカード', 'USB充電器', 'ポータブルHDD')
('SDカード', 'USB充電器', 'WiFiルーター')
('SDカード', 'キーボード', 'ポータブルHDD')
('SDカード', 'キーボード', 'WiFiルーター')
('マウス', 'Webカメラ', 'ポータブルHDD')
('マウス', 'Webカメラ', 'WiFiルーター')
('マウス', 'USB充電器', 'ポータブルHDD')
('マウス', 'USB充電器', 'WiFiルーター')
('マウス', 'キーボード', 'ポータブルHDD')
('マウス', 'キーボード', 'WiFiルーター')

itertoolsはPythonに同梱されている標準ライブラリなので、import itertoolsを実行するだけで利用できます。

辞書を用いた応用例

以下のように「商品名と価格の辞書」がある時に、組み合わせの合計金額を計算する時にも便利です。

>>> ap = {"USBケーブル":780, "SDカード":870, "マウス":940}
>>> bp = {"Webカメラ":3100, "USB充電器":2850, "キーボード":2600}
>>> cp = {"ポータブルHDD":8800, "WiFiルーター":9200}

以下のようにリスト内包表記zip()関数、sum()関数を活用すると、簡単に「福袋の中身の合計金額」も計算できます。

>>> for fuku in itertools.product(ap, bp, cp):
	print(fuku, sum([ d[k] for d,k in zip((ap, bp, cp),fuku) ]))

	
('USBケーブル', 'Webカメラ', 'ポータブルHDD') 12680
('USBケーブル', 'Webカメラ', 'WiFiルーター') 13080
('USBケーブル', 'USB充電器', 'ポータブルHDD') 12430
('USBケーブル', 'USB充電器', 'WiFiルーター') 12830
('USBケーブル', 'キーボード', 'ポータブルHDD') 12180
('USBケーブル', 'キーボード', 'WiFiルーター') 12580
('SDカード', 'Webカメラ', 'ポータブルHDD') 12770
('SDカード', 'Webカメラ', 'WiFiルーター') 13170
('SDカード', 'USB充電器', 'ポータブルHDD') 12520
('SDカード', 'USB充電器', 'WiFiルーター') 12920
('SDカード', 'キーボード', 'ポータブルHDD') 12270
('SDカード', 'キーボード', 'WiFiルーター') 12670
('マウス', 'Webカメラ', 'ポータブルHDD') 12840
('マウス', 'Webカメラ', 'WiFiルーター') 13240
('マウス', 'USB充電器', 'ポータブルHDD') 12590
('マウス', 'USB充電器', 'WiFiルーター') 12990
('マウス', 'キーボード', 'ポータブルHDD') 12340
('マウス', 'キーボード', 'WiFiルーター') 12740

itertoolsは強力です

itertoolsは、今回のproduct()のようなイテレータを構築するツールを集めたライブラリです。他にも様々なツールが実装されていますので、ぜひ以下の公式ドキュメントを一度ご覧ください。

itertools — 効率的なループ実行のためのイテレータ生成関数 (Python公式ドキュメント)