2016-09-15 3 views
2

Wie würde ich die Kombinationsfunktion von itertools richtig verwenden, um die Liste einmal, b zweimal ohne Ersatz, c zweimal ohne Ersatz und d und e einmal zu verwenden ?Zusammenstellen von Listen mit itertools

[[[2, 3],[5, 6],[7, 8],[11, 12],[13, 14],[15, 16],[12,16]], 
[[2, 3],[5, 6],[7, 8],[11, 12],[13, 14],[15, 16],[13,17]], 
[[2, 3],[5, 6],[7, 8],[11, 12],[13, 14],[15, 16],[14,18]], 
[[2, 3],[5, 6],[7, 8],[11, 12],[13, 14],[15, 16],[15,19]], 
[[2, 3],[5, 6],[7, 8],[11, 12],[13, 14],[15, 16],[12,16]],... 
[[3, 4],[7, 8],[9, 10],[11, 12], [13, 14],[17, 18],[15,19]]] 
+1

Sind die zwei Unentschieden aus ' b' mit oder ohne Ersatz? –

+1

Ich bin mir nicht sicher, ob ich verstehe, was Sie hier wollen (können Sie die ersten Beispielausgaben oder etwas geben, um sicher zu sein?), Aber wenn Sie "itertools.combinations" in 'list' für eine anständige Anzahl von Eingaben wickeln ist fast garantiert, um Ihre Erinnerung zu blasen.Die Anzahl der Ausgaben wächst um ungefähr "O (n!)" (Faktorielles Wachstum); Normalerweise wird von Ihnen erwartet, dass Sie die Kombinationen nacheinander durchlaufen und nicht alle auf einmal speichern. – ShadowRanger

+0

Ohne Ersatz, –

Antwort

2

Es scheint, wie Sie sich für eine Kombination aus combinations und product suchen: Verwenden Sie combinations die möglichen Kombinationen ohne Ersatz für die wiederholten Listen zu bekommen, dann product verwenden all diese Kombinationen zu kombinieren. Sie können die Listen und Zählungen in zwei Listen, zip diese Listen, setzen und einen Generatorausdruck verwenden, um alle Kombinationen zu erhalten.

from itertools import product, combinations, chain 
lists = [a,b,c,d,e] 
counts = [1,2,2,1,1] 
combs = product(*(combinations(l, c) for l, c in zip(lists, counts))) 

In diesem Beispiel hat der combs Generator 48 Elemente, unter anderem:

[(([2, 3],), ([5, 6], [7, 8]), ([11, 12], [13, 14]), ([15, 16],), ([12, 16],)), 
... 
(([2, 3],), ([5, 6], [7, 8]), ([11, 12], [13, 14]), ([17, 18],), ([15, 19],)), 
(([2, 3],), ([5, 6], [9, 10]),([11, 12], [13, 14]), ([15, 16],), ([12, 16],)), 
... 
(([3, 4],), ([5, 6], [7, 8]), ([11, 12], [13, 14]), ([15, 16],), ([12, 16],)), 
... 
(([3, 4],), ([5, 6], [7, 8]), ([11, 12], [13, 14]), ([17, 18],), ([15, 19],)), 
... 
(([3, 4],), ([7, 8], [9, 10]),([11, 12], [13, 14]), ([17, 18],), ([15, 19],))] 

Wenn Sie flattened lists wollen, nur chain sie:

>>> combs = (list(chain(*p)) for p in product(*(combinations(l, c) for l, c in zip(lists, counts)))) 
>>> list(combs) 
[[[2, 3], [5, 6], [7, 8], [11, 12], [13, 14], [15, 16], [12, 16]], 
... 
[[3, 4], [7, 8], [9, 10], [11, 12], [13, 14], [17, 18], [15, 19]]] 
+0

danke das ist genial –

1

Aktualisiert gegeben Klärung der erwarteten Ausgangs:

You want itertools.product:

itertools.product(a, b, b, c, c, c, c, d, e) 

die sich von jedem seiner Argumente auf jeder Iteration ein Element abholt, das schnellste das äußerste rechte Element Radfahren, ganz links am langsamsten.

können Sie erweiterte Argument Auspacken verwenden, um die Wiederholung bestimmter Argumente ein wenig mehr offensichtlich in Python 3 auszudrücken:

itertools.product(a, *[b]*2, *[c]*4, d, e) 

Oder tobias_k's solution für allgemeinere Wiederholung von Sequenzen verwendet werden (das wird auch auf Py2 arbeiten).

+1

Aber das wird nicht eine von a, zwei von b usw., aber nur 9 von allen zusammen ziehen. –

+1

@tobias_k: Ich habe geantwortet, bevor das OP die genaue Verwendung geklärt hat. Wird reparieren. – ShadowRanger

1

Was Ihr zu erreichen versuchen ist die Cartesian product of input iterables und nicht die Kombinationen des in der Liste vorhandenen Artikels. Daher müssen Sie stattdessen verwenden.

Bei Wiederholung unter den Listen erlaubt wird, die mehr als einmal verwendet, Antwort ist einfach:

>>> import itertools 
>>> a = [1,2] 
>>> b = [3,4] 
>>> [i for i in itertools.product(a, b, b)] 
[(1, 3, 3), (1, 3, 4), (1, 4, 3), (1, 4, 4), (2, 3, 3), (2, 3, 4), (2, 4, 3), (2, 4, 4)] 

Aber im Falle repetition is not allowed innerhalb der gleichen Listen, wird es wenig böse geworden und Sie müssen die oben kombinieren antworten Sie mit combinations() und chain() (selbe wie erwähnt durch tobias_k). Dieser Code wird die Liste aller combinations geben:

>>> from itertools import chain, product, combinations 
>>> lists, counts = [a, b], [1, 2] # to track that a is to be used once, and b twice 
>>> list(list(chain(*p)) for p in product(*(combinations(l, c) for l, c in zip(lists, counts)))) 
[[1, 3, 4], [2, 3, 4]] 

jedoch, falls Sie Permutationen statt Kombinationen benötigen, müssen Sie mit permutations() den obigen Code aktualisieren:

>>> from itertools import chain, product, permutations 
>>> list(list(chain(*p)) for p in product(*(permutations(l, c) for l, c in zip(lists, counts)))) 
[[1, 3, 4], [1, 4, 3], [2, 3, 4], [2, 4, 3]] 
+1

Nicht ganz klar aus der Frage, aber ich denke, dann sollte die letzte Zeile in der erwarteten Ausgabe enthalten '[13, 14], [11, 12]' statt '[11, 12], [ 13, 14] '. –

+1

@tobias_k Wenn ich auf seine Beispielausgabe schaue, glaube ich, dass er ein kartesisches Produkt der Listen benötigt. Die Antwort wurde mit einem einfachen Beispiel aktualisiert. Und ich stimme Ihnen zu, die bereitgestellten Parameter sind zu groß und geben keinen klaren Einblick in seine Absicht. Einfacheres Beispiel wäre hilfreich –

+0

Reihenfolge ist nicht wichtig –

Verwandte Themen