2016-03-24 6 views
7

Ich weiß, dass ich itertools abzupumpen Kombinationen verwenden kann, und die Größe der Kombinationsgruppe definieren, etwa so:2^n itertools Kombinationen mit erweiterten Filter

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

Der Ausgang dieses wie ein wäre Liste von Tupeln, jeweils von Länge 4 in diesem Fall.

Von hier aus möchte ich 2 Parameter erzwingen - 1) alle Kombinationen/Tupel ausschließen, die bestimmte Paare enthalten - sowohl V als auch M, oder Q und K. 2) Erzwinge jedes enthaltene Tupel nur 1 Instanz eines Briefes. Ich glaube, dass itertools bereits # 2 macht.

Was übrig bleiben soll, sind nur die Tupelgruppen, die keines dieser vorbestimmten "falschen" Paare enthalten. Wenn ich also eine Gruppe ausschließen würde, die V und M enthält, wäre die Gruppe ('V','M','Q','D') ungültig, aber ('V','R','Q','D') wäre gültig.

Was ist der beste Weg für mich, dies zu tun?

+0

Sie müssen nur manuell Bar filtern Sie rollen Ihre eigene Implementierung –

Antwort

1

ich mit einem Satz Filter würde:

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

Wenn Sie auf ein zwei filtern möchten:

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

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

Wenn Sie mehr als zwei wäre es wahrscheinlich schöner sein any zu verwenden:

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

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

Bar Sie rollen Ihre eigene Kombinationslogik, Sie können nicht vermeiden, alle Kombinationen zu erstellen a nd Filterung, auch wenn Sie Ihre eigene rollen sie in reinem Python tut wahrscheinlich langsame bar sein würde, wenn Sie eine große Datenmenge

0

Sie eine Liste Verständnis mit einem if Zustand verwenden können:

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

Beachten Sie jedoch , dass dies immer noch alle Kombinationen durchläuft und nur die ungültigen "wegwirft". Wenn z. B. die ersten beiden Elemente ('V','M') sind, wird weiterhin '(' V ',' M ',' O ',' R ') erzeugt und weggeworfen und so weiter. Für die Anzahl der in diesem Fall generierten Kombinationen ist das kein Problem. Bei größeren Kombinationen möchten Sie möglicherweise ungültige Teilergebnisse früher mit einem benutzerdefinierten rekursiven Algorithmus löschen.

3

können Sie eine Prüf-Funktion definieren und Filter mit dieser

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

Um es noch flexibler zu machen, können Sie eine Funktion machen können, die Validierungsfunktionen machen, und mischen Sie es mit der Idee @PadraicCunningham der Verwendung eingestellt

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

die make_validator nehmen als Argumente eine beliebige Anzahl von t er Ausschluss-Kombinationen, die Sie nicht wollen und eine Funktion machen, die die Überprüfung durchführen und sie zurückgeben; Sie können das Ergebnis in einer Variablen behalten oder direkt verwenden

+0

Dies ist genau das, was ich gesucht habe, in Bezug auf Flexibilität und Geschwindigkeit. Ich wusste nicht, dass Iertools auch eine Zeichenkette teilen würde, bis ich das sah. – DNburtonguster

+0

Zeichenkette sind wie eine Liste von Zeichen, also ist die Weitergabe einer Zeichenkette oder einer Literal-Liste von Zeichen identisch mit jeder Funktion, die mit iterables – Copperfield

+0

für zusätzliche Flexibilität arbeiten, können Sie eine Fabrik von Validatoren wie in meinem neuen Zusatz machen – Copperfield