2012-10-09 9 views
11

Ich habe eine Liste von Listen und eine Trenn-String wie folgt aus:Get trat Zeichenfolge aus der Liste der Listen von Zeichenketten in Python

lists = [ 
    ['a', 'b'], 
    [1, 2], 
    ['i', 'ii'], 
] 
separator = '-' 

Als Ergebnis, das ich eine Liste von Strings mit Trenn-String aus der Kombination haben wollen Zeichenfolgen in den Unterlisten:

result = [ 
    'a-1-i', 
    'a-1-ii', 
    'a-2-i', 
    'a-2-ii', 
    'b-1-i', 
    'b-1-ii', 
    'b-2-i', 
    'b-2-ii', 
] 

Reihenfolge in Ergebnis ist irrelevant.

Wie kann ich das tun?

+0

Im Moment bin ich nicht sicher, wie in einem schönen pythonic Weg, um diese Funktion zu erhalten, und es ist keine Hausaufgaben;) – Martin

Antwort

16
from itertools import product 
result = [separator.join(map(str,x)) for x in product(*lists)] 

itertools.product gibt einen Iterator, der das kartesische Produkt der bereitgestellten Iterables erzeugt. Wir müssen mapstr über die resultierenden Tupel, da einige der Werte sind ints. Schließlich können wir die stringifizierten Tupel verbinden und das Ganze in ein Listenverständnis (oder einen Generatorausdruck, wenn es sich um ein großes Dataset handelt, und Sie brauchen es nur für die Iteration) werfen.

+1

+1 Große Antwort Mann - ich möchte das ausdrucken und auf meinen Kühlschrank stellen. – RocketDonkey

3
>>> from itertools import product 
>>> result = list(product(*lists)) 
>>> result = [separator.join(map(str, r)) for r in result] 
>>> result 
['a-1-i', 'a-1-ii', 'a-2-i', 'a-2-ii', 'b-1-i', 'b-1-ii', 'b-2-i', 'b-2-ii'] 

Wie @jpm wies darauf hin, brauchen Sie nicht wirklich list zum product Generator zu werfen. Ich hatte diese, um die Ergebnisse in meiner Konsole zu sehen, aber sie werden hier nicht wirklich benötigt.

+0

Sie müssen das Produkt nicht in einen 'Listen'-Konstruktor zwingen. 'map' funktioniert auf einem Iterator einwandfrei. Außerdem müssen Sie die Tupel in diesem Iterator nicht in Listen erzwingen. 'map' und' join' funktionieren auf Tupel einwandfrei. – jpm

+0

@jpm ja, ich habe das noch bearbeitet. Anfangs hatte ich diese beim Versuch in meiner Konsole die Ergebnisse zu sehen, hätte sie später entfernen sollen :) –

+1

Ein weiterer Punkt zwingt den Iterator in eine Zwischenliste: Wenn das kartesische Produkt groß wird (ein durchaus mögliches Szenario, trotz was dieses Beispiel zeigt), wir wollen wahrscheinlich alles so lange wie möglich in Erinnerung behalten. Abhängig von der Anwendung möchten wir vielleicht sogar einen Generatorausdruck anstelle eines Listenverständnisses verwenden. – jpm

1
["%s%c%s%c%s" % (a, separator, b, separator, c) for a in lists[0] for b in lists[1] for c in lists[2]] 
3

Sie können dies mit builtins:

>>> map(separator.join, reduce(lambda c,n: [a+[str(b)] for b in n for a in c], lists, [[]])) 
['a-1-i', 'b-1-i', 'a-2-i', 'b-2-i', 'a-1-ii', 'b-1-ii', 'a-2-ii', 'b-2-ii'] 
+0

Nette Verwendung der funktionellen Techniken. Wenn Sie die For-Klauseln des Verständnisses umschalten, können Sie sogar die vom OP angeforderte Ausgabe abgleichen. – jpm

+0

Als ein Punkt von Interesse, ist diese Lösung sehr wenig langsamer als meins (nicht ganz 2 Sekunden über 2.000.000 Wiederholungen, über Zeit). Kaum genug, um sich in fast jeder Anwendung zu sorgen, aber ich fand es interessant. – jpm

+0

Danke. Ich habe nicht zu viel über die Reihenfolge der Bedingungen nachgedacht, aber das OP sagte, dass er sich nicht um den Auftrag kümmerte. – Benedict

Verwandte Themen