3
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

辞書型データのvalueの直積を返したい

Last updated at Posted at 2019-07-09

やりたいこと

pythonで、辞書が持つvalue同士の直積を、対応するkeyを変えずに辞書としてそれぞれ出力したい。

具体的には

{'A':[1,2,3], 'B':[4,5]}

という辞書が存在するときに

[{'A':1, 'B':4}, {'A':1, 'B':5},
 {'A':2, 'B':4}, {'A':2, 'B':5},
 {'A':3, 'B':4}, {'A':3, 'B':5}]

といった具合のリストが得られるようにしたい。

前提知識

itertools.product()で直積を求められます。

https://docs.python.org/ja/3/library/itertools.html#itertools.product

実装

test1.py
import itertools

test1 = {'A': [1, 2, 3], 'B': [4, 5]}

product = [x for x in itertools.product(*test1.values())]
result = [dict(zip(test1.keys(), r)) for r in product]
for r in result:
    print(r)
console
{'A': 1, 'B': 4}
{'A': 1, 'B': 5}
{'A': 2, 'B': 4}
{'A': 2, 'B': 5}
{'A': 3, 'B': 4}
{'A': 3, 'B': 5}

valueの型が異なっていてもOK

test2.py
import itertools

test2 = {'A': ['TEST', 1, 2.5], 'B': [[3, 4], 5]}

product = [x for x in itertools.product(*test2.values())]
result = [dict(zip(test1.keys(), r)) for r in product]
for r in result:
    print(r)
console
{'A': 'TEST', 'B': [3, 4]}
{'A': 'TEST', 'B': 5}
{'A': 1, 'B': [3, 4]}
{'A': 1, 'B': 5}
{'A': 2.5, 'B': [3, 4]}
{'A': 2.5, 'B': 5}

注意点

直積を求めたい辞書のvalueはlist型でなければなりません。
例えば以下の様な辞書を変換しようとするとエラーとなります。

test3.py
import itertools

test3 = {'A': 1, 'B': [2, 3], 'C': [4, 5, 6]}

product = [x for x in itertools.product(*test3.values())]
result = [dict(zip(test1.keys(), r)) for r in product]
for r in result:
    print(r)
console
Traceback (most recent call last):
  File "test3.py", line 5, in <module>
    product = [x for x in itertools.product(*test1.values())]
TypeError: 'int' object is not iterable

この様な場合は一旦valueを舐めてlistでなければlistに変換してあげれば良いです。

test4.py
import itertools

test4 = {'A': 1, 'B': [2, 3], 'C': [4, 5, 6]}

test4_after = dict([(key, val if type(val) is list else [val]) for key, val in test4.items()])

product = [x for x in itertools.product(*test4_after.values())]
result = [dict(zip(test4_after.keys(), r)) for r in product]
for r in result:
    print(r)
console
{'A': 1, 'B': 2, 'C': 4}
{'A': 1, 'B': 2, 'C': 5}
{'A': 1, 'B': 2, 'C': 6}
{'A': 1, 'B': 3, 'C': 4}
{'A': 1, 'B': 3, 'C': 5}
{'A': 1, 'B': 3, 'C': 6}

key値を捨てる場合

key値を捨ててvalueの直積だけ欲しい場合はzipの部分を消せばOK。

test5.py
import itertools

test5 = {'A': [1, 2], 'B': [4, 5, 6]}

product = [x for x in itertools.product(*test5.values())]
for r in product:
    print(r)
console
(1, 4)
(1, 5)
(1, 6)
(2, 4)
(2, 5)
(2, 6)
3
5
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?