2016-03-24 70 views
7

Itertools組合我知道我可以使用itertools泵出的組合,並且限定了組合組的大小,像這樣:2^n,其中高級過濾

import itertools 
print list(itertools.combinations(['V','M','T','O','Q','K','D','R'], 4)) 

的這個輸出會像元組列表,每個元組的長度都是4。

從這裏,我想要做的是強制執行2個參數 - 1)排除包含某些對的任何組合/元組,例如V和M,或者Q和K. 2)強制每個元組包含只有一個字母的例子。我相信itertools已經在做#2。

應該保留的只是那些不包含任何這些預定義的「假」對的元組。因此,如果我排除了包含V和M的組,那麼組('V','M','Q','D')將無效,但('V','R','Q','D')將有效。

我這樣做的最好方法是什麼?

+0

您只需手動過濾條即可自行實施 –

回答

1

我會用一組濾波器:

import itertools 
c = itertools.combinations(['V','M','T','O','Q','K','D','R'], 4) 

st = {"V","M"} 

print([co for co in c if not st.issubset(co)]) 

如果你想在兩個過濾:

st1 = {"V","M"} 
st2 = {"Q","K"} 

print([co for co in c if not st1.issubset(co) and not st2.issubset(co)]) 

如果有兩個以上這將是可能更好使用any

sts = [{"V","M"},{"V","R"},{"T","O"}] 

print([co for co in c if not any(st.issubset(co) for st in sts)]) 

酒吧你滾自己的組合邏輯,你不能避免創建所有的組合ND過濾,即使你滾你自己的純Python這樣做可能會慢一些吧,你有一個大的數據集

0

您可以使用列表理解與if條件:

>>> [x for x in itertools.combinations('VMTOQKDR', 4) 
     if not (('V' in x and 'M' in x) or ('Q' in x and 'K' in x))] 
[('V', 'T', 'O', 'Q'), 
('V', 'T', 'O', 'K'), 
... 37 more ... 
('O', 'Q', 'D', 'R'), 
('O', 'K', 'D', 'R')] 

但是請注意, ,這仍然會通過所有的組合,只是「扔掉」無效的組合。例如,如果前兩個元素是('V','M'),它將繼續生成'('V','M','O','R')並將其扔掉,依此類推。在這種情況下生成的組合的數量不是問題。對於較大的組合,您可能想要使用自定義遞歸算法提前丟棄無效的部分結果。

3

你可以定義一個驗證功能,並與

>>> import itertools 
>>> def is_valid(data): 
     if 'V' in data and 'M' in data: 
      return False 
     if 'Q' in data and 'K' in data: 
      return False 
     return True 

>>> filter(is_valid,itertools.combinations('VMTOQKDR', 4)) 
[('V', 'T', 'O', 'Q'), ('V', 'T', 'O', 'K'), ('V', 'T', 'O', 'D'), ('V', 'T', 'O', 'R'), ('V', 'T', 'Q', 'D'), ('V', 'T', 'Q', 'R'), ('V', 'T', 'K', 'D'), ('V', 'T', 'K', 'R'), ('V', 'T', 'D', 'R'), ('V', 'O', 'Q', 'D'), ('V', 'O', 'Q', 'R'), ('V', 'O', 'K', 'D'), ('V', 'O', 'K', 'R'), ('V', 'O', 'D', 'R'), ('V', 'Q', 'D', 'R'), ('V', 'K', 'D', 'R'), ('M', 'T', 'O', 'Q'), ('M', 'T', 'O', 'K'), ('M', 'T', 'O', 'D'), ('M', 'T', 'O', 'R'), ('M', 'T', 'Q', 'D'), ('M', 'T', 'Q', 'R'), ('M', 'T', 'K', 'D'), ('M', 'T', 'K', 'R'), ('M', 'T', 'D', 'R'), ('M', 'O', 'Q', 'D'), ('M', 'O', 'Q', 'R'), ('M', 'O', 'K', 'D'), ('M', 'O', 'K', 'R'), ('M', 'O', 'D', 'R'), ('M', 'Q', 'D', 'R'), ('M', 'K', 'D', 'R'), ('T', 'O', 'Q', 'D'), ('T', 'O', 'Q', 'R'), ('T', 'O', 'K', 'D'), ('T', 'O', 'K', 'R'), ('T', 'O', 'D', 'R'), ('T', 'Q', 'D', 'R'), ('T', 'K', 'D', 'R'), ('O', 'Q', 'D', 'R'), ('O', 'K', 'D', 'R')] 
>>> 

編輯

過濾器,以使其更加靈活,你可以做一個函數,使驗證功能,並將其與混合想法@PadraicCunningham使用集

>>> import itertools 
>>> def make_validator(*checks): 
     checker=[set(x) for x in checks] 
     def validator(data): 
      return not any(st.issubset(data) for st in checker) 
     return validator 

>>> is_valid = make_validator("VM","QK") 
>>> filter(is_valid, itertools.combinations('VMTOQKDR', 4)) 
[('V', 'T', 'O', 'Q'), ('V', 'T', 'O', 'K'), ('V', 'T', 'O', 'D'), ('V', 'T', 'O', 'R'), ('V', 'T', 'Q', 'D'), ('V', 'T', 'Q', 'R'), ('V', 'T', 'K', 'D'), ('V', 'T', 'K', 'R'), ('V', 'T', 'D', 'R'), ('V', 'O', 'Q', 'D'), ('V', 'O', 'Q', 'R'), ('V', 'O', 'K', 'D'), ('V', 'O', 'K', 'R'), ('V', 'O', 'D', 'R'), ('V', 'Q', 'D', 'R'), ('V', 'K', 'D', 'R'), ('M', 'T', 'O', 'Q'), ('M', 'T', 'O', 'K'), ('M', 'T', 'O', 'D'), ('M', 'T', 'O', 'R'), ('M', 'T', 'Q', 'D'), ('M', 'T', 'Q', 'R'), ('M', 'T', 'K', 'D'), ('M', 'T', 'K', 'R'), ('M', 'T', 'D', 'R'), ('M', 'O', 'Q', 'D'), ('M', 'O', 'Q', 'R'), ('M', 'O', 'K', 'D'), ('M', 'O', 'K', 'R'), ('M', 'O', 'D', 'R'), ('M', 'Q', 'D', 'R'), ('M', 'K', 'D', 'R'), ('T', 'O', 'Q', 'D'), ('T', 'O', 'Q', 'R'), ('T', 'O', 'K', 'D'), ('T', 'O', 'K', 'R'), ('T', 'O', 'D', 'R'), ('T', 'Q', 'D', 'R'), ('T', 'K', 'D', 'R'), ('O', 'Q', 'D', 'R'), ('O', 'K', 'D', 'R')] 
>>> filter(make_validator("VM","QK",'MT',"DR"), itertools.combinations('VMTOQKDR', 4)) 
[('V', 'T', 'O', 'Q'), ('V', 'T', 'O', 'K'), ('V', 'T', 'O', 'D'), ('V', 'T', 'O', 'R'), ('V', 'T', 'Q', 'D'), ('V', 'T', 'Q', 'R'), ('V', 'T', 'K', 'D'), ('V', 'T', 'K', 'R'), ('V', 'O', 'Q', 'D'), ('V', 'O', 'Q', 'R'), ('V', 'O', 'K', 'D'), ('V', 'O', 'K', 'R'), ('M', 'O', 'Q', 'D'), ('M', 'O', 'Q', 'R'), ('M', 'O', 'K', 'D'), ('M', 'O', 'K', 'R'), ('T', 'O', 'Q', 'D'), ('T', 'O', 'Q', 'R'), ('T', 'O', 'K', 'D'), ('T', 'O', 'K', 'R')] 
>>> 

make_validator作爲參數任意數量的t他排除了你不想要的組合,並製作一個執行檢查並返回的功能;您可以將結果保留在變量中或直接使用

+0

這正是我在尋找的靈活性和速度。我不知道itertools也會分割一個字符串,直到我看到這個。 – DNburtonguster

+0

字符串類似於字符列表,因此傳遞字符串或文字列表的字符與任何使用迭代器 – Copperfield

+0

的函數相同以增加靈活性,因此可以使驗證工廠成爲新增加的工廠 – Copperfield