2016-10-31 6 views
3

Ich möchte eine Liste von Listen aus einer Liste von Multi-Feld-Strings erstellen und frage mich, ob es möglich ist, dies in einem Verständnis zu tun.mehrere Variablen im Listenverständnis?

Eingang:

inputs = ["1, foo, bar", "2, tom, jerry"] 

gewünschte Ausgabe:

[[1, "foo", "bar"], [2, "tom", "jerry"]] 

Splitting der String in einem Verständnis ist einfach:

>>> [s.split(",") for s in inputs] 
[['1', ' foo', ' bar'], ['2', ' tom', ' jerry']] 

Aber ich habe Probleme, herauszufinden, wie man Zugang Die Spalten nach der Zeichenkette wurden innerhalb des Verständnisses geteilt, da es eine Varia erfordern würde Zuweisung. Die folgenden sind nicht gültig Python, sondern zeigen, was ich suche:

[[int(x), y.strip(), z.strip() for x,y,z = s.split(",")] for s in inputs] 
    or 
[[int(v[0]), v[1].strip(), v[2].strip() for v = s.split(",")] for s in inputs] 

Gibt es eine Möglichkeit Variablen in einem Verständnis zuweisen, so dass die Ausgabe der Funktionen der Variablen zusammengesetzt werden können? Eine Schleife ist trivial, aber das Erzeugen einer Liste durch Transformieren von Eingaben scheint eine "Verständnis-ische" Aufgabe zu sein.

outputs = [] 
for s in inputs: 
    x,y,z = s.split(",") 
    outputs.append([int(x), y.strip(), z.strip()]) 
+0

Sie die Elemente mit ihrem Index zugreifen. Für '[['1', 'foo', 'bar'], ['2', 'tom', 'jerry']] ',' lst [0] [0] 'wäre' 1', 'lst [0] [1] 'wäre' foo' und so weiter. Wenn Sie Variablen benötigen, müssen Sie sie wahrscheinlich als Karten mit Schlüsseln speichern. – shaktimaan

+4

'[... für x, y, z in (s.split (',') für s in Eingängen)]' – jonrsharpe

Antwort

3

Sie können dies in Ihrer Liste Verständnis mit zwei for Klauseln tun. Der erste iteriert die Elemente in der Liste. Die zweite iteriert über eine Einzelpostenliste, die die Liste enthält, die aus der Aufteilung der Zeichenfolge abgeleitet wird (die benötigt wird, damit wir sie in drei separate Variablen entpacken können).

[[int(x), y.strip(), z.strip()] for s in inputs for (x, y, z) in [s.split(",")]] 

Die for Klauseln gehen in einer etwas eingängig Ordnung, aber es passt so, wie Sie es als verschachtelte for Schleifen schreiben würde.

Jon Sharpe Verwendung eines verschachtelten Verständnisses (Generator Ausdruck, tatsächlich) ist ähnlich und wahrscheinlich klarer. Die Verwendung von mehreren for Klauseln erscheint mir immer verwirrend; Hauptsächlich wollte ich sehen, ob ich es hier gebrauchen könnte.

1

Wenn Sie es wirklich in einer Linie tun wollen, können Sie etwas tun kann, obwohl es nicht der klarste Code ist (erste Zeile ist der Code, ist zweite Zeile der Ausgabe).

>>> [(lambda x, y, z: [int(x), y.strip(), z.strip()])(*s.split(",")) for s in inputs] 
[[1, 'foo', 'bar'], [2, 'tom', 'jerry']] 

Oder dies.

>>> [(lambda x: [int(x[0]), x[1].strip(), x[2].strip()])(s.split(",")) for s in inputs] 
[[1, 'foo', 'bar'], [2, 'tom', 'jerry'] 

Edit: See jonrsharpe Kommentar für die beste Antwort IMHO.

+0

Ich dachte über ein Lambda nach, hoffe aber, es möglichst zu vermeiden - danke für das Arbeitsbeispiel. – Dave

1

Sie Karte mit einer Liste Verständnis

def clean(x): 
    return [int(x[0]), x[1].strip(), x[2].strip()] 

map(clean,[s.split(",") for s in inputs]) 
# Output: [[1, 'foo', 'bar'], [2, 'tom', 'jerry']] 

mit einer Lambda-Funktion verwenden:

map(lambda x: [int(x[0]), x[1].strip(), x[2].strip()],[s.split(",") for s in inputs]) 
0

Eine andere mögliche Lösung

>>> inputs = [[1, "foo", "bar"], [2, "tom", "jerry"]] 
>>> list_of_dicts = [{"var{}".format(k): v for k, v in enumerate(s, start=1)} for s in inputs] 
>>> list_of_dicts[0]['var1'] 
1 
>>> list_of_dicts[0]['var2'] 
'foo' 
1

Vielen Dank für alle Vorschläge - es ist toll, die Vielfalt der möglichen Techniken, sowie ein Gegenbeispiel zu der zen von Pythons „Es sollte eine sein, zu sehen - und vorzugsweise nur eine - Offensichtlicher Weg, es zu tun."

Alle 4 Lösungen sind gleich schön, es ist also ein bisschen unfair, nur einer von ihnen den begehrten grünen Scheck zu geben. Ich stimme den Empfehlungen zu, dass # 1 der sauberste und beste Ansatz ist. # 2 ist auch Einfach zu verstehen, aber ein Lambda innerhalb eines Verständnisses zu verwenden, scheint ein bisschen aus. # 3 ist schön beim Erstellen eines Iterators mit Karte, aber bekommt einen winzigen Fehler für den zusätzlichen Schritt des Iterierens über. # 4 ist cool für das Aufzeigen die Verschachtelung ist möglich - wenn ich mich erinnern kann, dass sie in "erster, zweiter" Reihenfolge statt "innerer, äußerer" geht. Da # 1 nicht in Form einer Antwort ist, bekommt # 4 den Scheck am überraschendsten.

Vielen Dank nochmal an alle

inputs = ["1, foo, bar", "2,tom, jerry"] 

outputs1 = [[int(x), y.strip(), z.strip()] for x,y,z in (s.split(',') for s in inputs)] 
print("1:", outputs1)  # jonrsharpe 

outputs2 = [(lambda x, y, z: [int(x), y.strip(), z.strip()])(*s.split(",")) for s in inputs] 
print("2:", outputs2)  # yper 

outputs3 = [z for z in map(lambda x: [int(x[0]), x[1].strip(), x[2].strip()],[s.split(",") for s in inputs])] 
print("3:", outputs3)  # user2314737 

outputs4 = [[int(x), y.strip(), z.strip()] for s in inputs for (x, y, z) in [s.split(",")]] 
print("4:", outputs4)  # kindall 

Ergebnisse:

1: [[1, 'foo', 'bar'], [2, 'tom', 'jerry']] 
2: [[1, 'foo', 'bar'], [2, 'tom', 'jerry']] 
3: [[1, 'foo', 'bar'], [2, 'tom', 'jerry']] 
4: [[1, 'foo', 'bar'], [2, 'tom', 'jerry']]