2016-03-24 101 views
7

so che posso usare itertools per pompare fuori combinazioni, e definire la dimensione del gruppo di combinazione, in questo modo:2^n combinazioni itertools con filtraggio avanzato

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

L'uscita di questo sarebbe come un lista di tuple, ciascuna della lunghezza 4 in questo caso.

Da qui, ciò che mi piacerebbe fare è applicare 2 parametri - 1) escludere qualsiasi combinazione/tupla che contenga determinate coppie - sia V che M per esempio, o Q e K. 2) Forza ogni tupla a contenere solo 1 istanza di una lettera. Credo che itertools stia già facendo # 2.

Quello che dovrebbe rimanere sono solo quei gruppi di tuple che non contengono nessuna di queste coppie "false" predeterminate. Quindi, se escludessi un gruppo che conteneva V e M, il gruppo ('V','M','Q','D') non sarebbe valido, ma ('V','R','Q','D') sarebbe valido.

Qual è il modo migliore per fare questo?

+0

Devi solo filtrare manualmente la barra per il rollover della tua implementazione –

risposta

1

avrei filtrare con un set:

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)]) 

Se si desidera filtrare su un due:

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

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

Se si dispone di più di due sarebbe probabilmente più bello da usare any:

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

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

Bar si rotola la propria logica di combinazione, non è possibile evitare di creare tutte le combinazioni un filtraggio nd, anche se tira il proprio farlo in puro python sarebbe probabilmente bar più lento si ha un grande insieme di dati

0

È possibile utilizzare un elenco di comprensione con una if condizione:

>>> [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')] 

Si noti, tuttavia , che questo continuerà ad attraversare tutte le combinazioni e semplicemente "getterà via" quelle non valide. Ad esempio, se i primi due elementi sono ('V','M'), continuerà a generare `('V', 'M', 'O', 'R') e lo getterà via, e così via. Per il numero di combinazioni generate in questo caso non è un problema. Per combinazioni più grandi, potresti voler eliminare i risultati parziali non validi in precedenza, usando un algoritmo ricorsivo personalizzato.

3

si può definire una funzione validate e filtrare con quella

>>> 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')] 
>>> 

EDIT

Per rendere ancora più flessibile, è possibile effettuare una funzione che fanno funzioni di validazione, e mescolare con la idea di @PadraicCunningham di usare impostato

>>> 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')] 
>>> 

la make_validator presa come argomenti qualsiasi numero di t le combinazioni di esclusione che non vuoi e fanno una funzione che esegue il controllo e la restituisce; puoi mantenere il risultato in una variabile o usarlo direttamente

+0

Questo è esattamente quello che stavo cercando, in termini di flessibilità e velocità. Non ero a conoscenza del fatto che gli eolici avrebbero diviso anche una stringa di caratteri, finché non l'ho visto.La stringa – DNburtonguster

+0

è come un elenco di caratteri, quindi passare una stringa o un elenco letterale di caratteri è uguale a qualsiasi funzione che funzioni con iterables – Copperfield

+0

per maggiore flessibilità, è possibile creare una factory di validatori come nella mia nuova aggiunta – Copperfield