制限

2017-06-05 12 views
0

とPythonの辞書のすべてのサブセットを取得し、私持って、次の辞書:私は「paramx」の各番号xの正確に一つを持っている必要があります。この辞書のすべての可能なサブセットを作成する方法を制限

intervals = {'param1': [0, 1], 
      'param2_hi': [4, 5, 6, 7, 8, 9], 
      'param2_lo': [0, 1, 2, 3, 4, 5], 
      'param3_hi': [9, 10, 11, 12, 13, 14, 15], 
      'param3_lo': [5, 6, 7, 8, 9, 10], 
      'param4': [0, 1], 
      'param5_hi': [4, 5, 6, 7, 8, 9], 
      'param5_lo': [0, 1, 2, 3, 4, 5]} 

?つまり、param1(_loまたは_hi)、param2(_loまたは_hi)のエントリなどが1つしかなく、各サブセットには_loまたは_hiがないすべてのparamxが含まれている必要があります。

subset_one = {'param1': [0, 1], 
       'param2_hi': [4, 5, 6, 7, 8, 9], 
       'param3_hi': [9, 10, 11, 12, 13, 14, 15], 
       'param4': [0, 1], 
       'param5_hi': [4, 5, 6, 7, 8, 9]} 

subset_two = {'param1': [0, 1], 
       'param2_lo': [0, 1, 2, 3, 4, 5], 
       'param3_lo': [5, 6, 7, 8, 9, 10], 
       'param4': [0, 1], 
       'param5_lo': [0, 1, 2, 3, 4, 5]} 

# Example of mixed '_hi' and '_lo' intervals 
subset_three = {'param1': [0, 1], 
       'param2_lo': [0, 1, 2, 3, 4, 5], 
       'param3_hi': [9, 10, 11, 12, 13, 14, 15], 
       'param4': [0, 1], 
       'param5_lo': [0, 1, 2, 3, 4, 5]} 

... 

注:私は、キーを保存したい、と値のペア。ここ

は、2つの可能なサブセットです。

編集: '_lo'と '_hi'の間隔が混在する可能性を示すためにsubset_threeが追加されました。

+0

これは唯一の鍵ですか? –

+0

これはパラメータの有限リストですか、それらは実際の名前ですか?そして、常に増分の順番で番号が付けられていますか? – zwer

+0

私のプログラムのさまざまな実行によっては、もっと多くなることがありますが、キーは常にparamx、paramx_lo、paramx_hiという形式になります(xは整数)。 –

答えて

1

は、私は両方collections.defaultdictitertools.productはここに有用であろうと思います。まず、キーのソートに基づいてキーをソートするプールを構築します。次に、これらのビンのデカルト積を構築する。

from collections import defaultdict 
from itertools import product 

pool = defaultdict(list) 
for key in intervals: 
    base = key.split('_')[0] 
    pool[base].append(key) 

subsets = [{key: intervals[key] for key in keys} for keys in product(*pool.values())] 

# {'param2_lo': [0, 1, 2, 3, 4, 5], ... , 'param1': [0, 1]} 
# {'param5_lo': [0, 1, 2, 3, 4, 5], ..., 'param2_hi': [4, 5, 6, 7, 8, 9]} 
# and so on... 
+0

'itertools。product() 'は、個々のキーを保持する' interval 'のように、あなたの辞書の理解に失敗するタプル要素を持つイテレータを返します。 'subsets = [{key:キーのキーのためのキーのためのキー[keys] for product(* pool.values())]' – zwer

+0

@zwerが更新されました、 –

2

最も単純なケースでは、次の辞書内包表記を使用することがあります。

subset_1 = {k:v for k,v in intervals.items() if k.endswith('_hi') or not k.endswith('_lo')} 
subset_2 = {k:v for k,v in intervals.items() if k.endswith('_lo') or not k.endswith('_hi')} 

print(subset_1) 
print(subset_2) 

出力:

{'param3_hi': [9, 10, 11, 12, 13, 14, 15], 'param1': [0, 1], 'param2_hi': [4, 5, 6, 7, 8, 9], 'param4': [0, 1], 'param5_hi': [4, 5, 6, 7, 8, 9]} 
{'param2_lo': [0, 1, 2, 3, 4, 5], 'param1': [0, 1], 'param3_lo': [5, 6, 7, 8, 9, 10], 'param4': [0, 1], 'param5_lo': [0, 1, 2, 3, 4, 5]} 
+0

高い値と低い値の組み合わせがあります。私は各番号付きパラメータの1つを持っていなければなりません。 –

+0

@ToddYoung、拡張された精巧な条件と望ましい出力で質問を更新できますか? – RomanPerekhrest

+0

「_lo」と「_hi」の間隔が混在する可能性のある例である 'subset_three'が追加されました。 –

1

私はあなたがitertools.productがあなたのパラメータの5つの選択肢のセットに適用したいと考えてい:

choices = [ 
    ['param1'], 
    ['param2_lo', 'param2_hi'], 
    ['param3_lo', 'param3_hi'], 
    ['param4'], 
    ['param5_lo', 'param5_hi'] 
] 

for permute in itertools.product(*choices): 
    .... 

は、あなたが軌道に乗るためにそれが十分ですか?

+1

が必要です'(* choices)'を使用すると思います。 – DSM

0

私が使用するのに最適なツールがitertools.productで、一つの解決策は、このことだと思う:

intervals = {'param1': [0, 1], 
      'param2_hi': [4, 5, 6, 7, 8, 9], 
      'param2_lo': [0, 1, 2, 3, 4, 5], 
      'param3_hi': [9, 10, 11, 12, 13, 14, 15], 
      'param3_lo': [5, 6, 7, 8, 9, 10], 
      'param4': [0, 1], 
      'param5_hi': [4, 5, 6, 7, 8, 9], 
      'param5_lo': [0, 1, 2, 3, 4, 5]} 


import itertools 

def get_subsets(intervals): 

    params_list = set(key.split('_')[0] for key in intervals.keys()) 

    list_keys = [[x for x in intervals.keys() if x.startswith(param)] for param in params_list] 

    subsets = [{x : intervals[x] for x in sublist} for sublist in itertools.product(*list_keys)] 

    return subsets 

get_subsets(intervals) 

# [{'param2_lo': [0, 1, 2, 3, 4, 5], 'param3_hi': [9, 10, 11, 12, 13, 14, 15], 'param5_lo': [0, 1, 2, 3, 4, 5], 'param1': [0, 1], 'param4': [0, 1]}, {'param2_lo': [0, 1, 2, 3, 4, 5], 'param3_hi': [9, 10, 11, 12, 13, 14, 15], 'param1': [0, 1], 'param4': [0, 1], 'param5_hi': [4, 5, 6, 7, 8, 9]}, ... 
0

あなたはすべての可能な組み合わせをリストアップするために、この例のようにitertoolsモジュールからgroupbyproductを使用することができます。

from itertools import groupby, product 

intervals = {'param1': [0, 1], 
      'param2_hi': [4, 5, 6, 7, 8, 9], 
      'param2_lo': [0, 1, 2, 3, 4, 5], 
      'param3_hi': [9, 10, 11, 12, 13, 14, 15], 
      'param3_lo': [5, 6, 7, 8, 9, 10], 
      'param4': [0, 1], 
      'param5_hi': [4, 5, 6, 7, 8, 9], 
      'param5_lo': [0, 1, 2, 3, 4, 5]} 


sub = [] 

for _,v in groupby(sorted(intervals.keys()), lambda x: x[5]): 
    # Or: 
    # sub.append(list(v)) 
    sub.append(sorted(list(v))) 


for k in product(*sub): 
    print({j:intervals[j] for j in k}) 
    print("------") 

出力:

{'param1': [0, 1], 'param3_hi': [9, 10, 11, 12, 13, 14, 15], 'param2_hi': [4, 5, 6, 7, 8, 9], 'param5_hi': [4, 5, 6, 7, 8, 9], 'param4': [0, 1]} 
------ 
{'param1': [0, 1], 'param3_hi': [9, 10, 11, 12, 13, 14, 15], 'param2_hi': [4, 5, 6, 7, 8, 9], 'param5_lo': [0, 1, 2, 3, 4, 5], 'param4': [0, 1]} 
------ 
{'param1': [0, 1], 'param2_hi': [4, 5, 6, 7, 8, 9], 'param5_hi': [4, 5, 6, 7, 8, 9], 'param3_lo': [5, 6, 7, 8, 9, 10], 'param4': [0, 1]} 
------ 
{'param1': [0, 1], 'param2_hi': [4, 5, 6, 7, 8, 9], 'param3_lo': [5, 6, 7, 8, 9, 10], 'param5_lo': [0, 1, 2, 3, 4, 5], 'param4': [0, 1]} 
------ 
.... 
------ 

{'param4': [0, 1], 'param1': [0, 1], 'param5_hi': [4, 5, 6, 7, 8, 9], 'param3_lo': [5, 6, 7, 8, 9, 10], 'param2_lo': [0, 1, 2, 3, 4, 5]} 
------ 
{'param4': [0, 1], 'param1': [0, 1], 'param5_lo': [0, 1, 2, 3, 4, 5], 'param3_lo': [5, 6, 7, 8, 9, 10], 'param2_lo': [0, 1, 2, 3, 4, 5]} 
------