web-dev-qa-db-ja.com

リストの辞書のデカルト積

一連の入力パラメーターのデカルト積をテストするためのコードを記述しようとしています。

私はitertoolsを見てきましたが、そのproduct関数は正確に私が望んでいるものではありません。任意の数のキーを持つディクショナリを取得する簡単な方法はありますかand各値に任意の数の要素があり、次の順列を持つディクショナリを生成しますか?

入力:

options = {"number": [1,2,3], "color": ["orange","blue"] }
print list( my_product(options) )

出力例:

[ {"number": 1, "color": "orange"},
  {"number": 1, "color": "blue"},
  {"number": 2, "color": "orange"},
  {"number": 2, "color": "blue"},
  {"number": 3, "color": "orange"},
  {"number": 3, "color": "blue"}
]
58
Seth Johnson

私が間違った場所を探していたと言ってくれて@dfanに感謝します。私はそれを今持っています:

_from itertools import product
def my_product(inp):
    return (dict(Zip(inp.keys(), values)) for values in product(*inp.values())
_

[〜#〜] edit [〜#〜]:数年後、さらにPython経験、より良い解決策はkwargsではなく入力の辞書;呼び出しスタイルは元の_itertools.product_に似ています。また、ジェネレータ式を返す関数ではなく、ジェネレータ関数を記述すると、コードがより明確になると思います。

_def product_dict(**kwargs):
    keys = kwargs.keys()
    vals = kwargs.values()
    for instance in itertools.product(*vals):
        yield dict(Zip(keys, instance))
_

dictを渡す必要がある場合は、list(product_dict(**mydict))を使用します。任意の入力クラスではなくkwargsを使用した注目すべき変更の1つは、少なくともPython 3.6になるまで、キー/値が順序付けされないようにすることです。

47
Seth Johnson

Python 3バージョンの Sethの答え

import itertools

def dict_product(dicts):
    """
    >>> list(dict_product(dict(number=[1,2], character='ab')))
    [{'character': 'a', 'number': 1},
     {'character': 'a', 'number': 2},
     {'character': 'b', 'number': 1},
     {'character': 'b', 'number': 2}]
    """
    return (dict(Zip(dicts, x)) for x in itertools.product(*dicts.values()))
16
Tarrasch

ちなみに、これは順列ではありません。順列は、リストの再配置です。これは、リストからの可能な選択の列挙です。

編集:それがデカルト積と呼ばれたことを思い出した後、私はこれを思いつきました:

import itertools
options = {"number": [1,2,3], "color": ["orange","blue"] }
product = [x for x in apply(itertools.product, options.values())]
print [dict(Zip(options.keys(), p)) for p in product]
6
dfan
# I would like to do
keys,values = options.keys(), options.values()
# but I am not sure that the keys and values would always
# be returned in the same relative order. Comments?
keys = []
values = []
for k,v in options.iteritems():
    keys.append(k)
    values.append(v)

import itertools
opts = [dict(Zip(keys,items)) for items in itertools.product(*values)]

結果は

opts = [
    {'color': 'orange', 'number': 1},
    {'color': 'orange', 'number': 2},
    {'color': 'orange', 'number': 3},
    {'color': 'blue', 'number': 1},
    {'color': 'blue', 'number': 2},
    {'color': 'blue', 'number': 3}
]
2
Hugh Bothwell