2017-08-12 28 views
1

我有以下字典:從字典結合所有可能的選項

d = { 
    'option1': range(0, 5), 
    'optionA': ['a', 'b', 'c'], 
    'extra_option': range(100, 200, 20) 
} 

我在尋找的代碼,會爲我提供一個數組,像這樣:

[ "--option1=0 --optionA=a --extra_option=100", 
    "--option1=0 --optionA=a --extra_option=120", 
    "--option1=0 --optionA=a --extra_option=140", 
    . 
    . 
    . 
    "--option1=5 --optionA=b --extra_option=180"] 

我已經看了在itertools產品和組合中,但兩者似乎都不適合這項工作。我想創建這樣一個發電機:

def get_options(d, keys): 
    key = keys.pop() 
    for key in d: 
     if len(keys) > 0: 
      for value in d[key]: 
       for other in get_options(d, keys[:]): 
        yield "--%s=%s %s" % (key, value, other) 
     else: 
      for value in d[key]: 
       yield "--%s=%s" % (key, value) 

for x in get_options(d, list(d.keys())): 
     print (x) 

但是,這給我的錯誤:

$ python3 test.py 
--optionA=a --optionA=a --optionA=a 
--optionA=a --optionA=a --optionA=b 
--optionA=a --optionA=a --optionA=c 
--optionA=a --optionA=a --option1=0 
--optionA=a --optionA=a --option1=1 
--optionA=a --optionA=a --option1=2 
--optionA=a --optionA=a --option1=3 
--optionA=a --optionA=a --option1=4 
--optionA=a --optionA=a --extra_option=100 
--optionA=a --optionA=a --extra_option=120 
--optionA=a --optionA=a --extra_option=140 
--optionA=a --optionA=a --extra_option=160 
--optionA=a --optionA=a --extra_option=180 
Traceback (most recent call last): 
    File "test.py", line 18, in <module> 
    for x in get_options(d, list(d.keys())): 
    File "test.py", line 12, in get_options 
    for other in get_options(d, keys): 
    File "test.py", line 12, in get_options 
    for other in get_options(d, keys): 
    File "test.py", line 8, in get_options 
    key = keys.pop() 
IndexError: pop from empty list 

這不是我所期待的......我在做什麼錯?任何人都可以告訴我一個更好的方法來做到這一點?提前致謝!

編輯10秒後:

哎呀,所以我還是不得不在那裏for key in d從以前的測試...去除(和取消縮進休息了一下),它的工作原理!但我的其他問題仍然存在,有沒有更好的方法來做到這一點?

+0

,如果你有工作,但要改善它,考慮http://codereview.stackexchange.com – davedwards

回答

2

事實上,Python提供了類似的功能,稱爲itertools.productitertools爲重複任務打包了許多有用的工具,例如組合,組合,鏈接等。

product將返回輸入迭代的笛卡爾乘積。

這是這樣的:

product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy 
product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111 

所以你只需要返回,在每一輪的改變與product。而時間複雜度將是O(n)的!

這是我改進的代碼:

from itertools import product 
from collections import OrderedDict 


d = { 
    'option1': range(0, 5), 
    'optionA': ['a', 'b', 'c'], 
    'extra_option': range(100, 200, 20) 
} 


#just make it beautiful 
def ordered(d): 
    temp = OrderedDict() 
    for key, value in d.items(): 
     temp[key] = value 
    return temp 


def merge(d): 
    dKeys = list(ordered(d).keys()) 
    keyStr = "={} --".join(dKeys) 
    keyStr = "--" + keyStr + "={}" 
    dValues = [list(value) for value in d.values()] 
    for value_list in product(*dValues): 
     yield keyStr.format(*value_list) 

for r in merge(d): 
    print(r) 
+0

,代碼會更清楚。如果你想了解更多關於'itertools'的信息,我建議你閱讀官方文檔。 (PS:我認爲用你的簡單代碼格式化'keyStr'是你問題中最難的部分) – WSY