2009-11-09 2 views
7

Ich mag wie etwas tun:Python: komplex Listenkomprehensionen wo man var auf einem anderen (x für x in t [1] für t in Tests) hängt

all = [ x for x in t[1] for t in tests ] 

Tests wie folgt aussieht:

[ ("foo",[a,b,c]), ("bar",[d,e,f]) ] 

Deshalb möchte ich das Ergebnis haben

all = [a,b,c,d,e,f] 

Mein Code funktioniert nicht, Python sagt:

Gibt es eine einfache Möglichkeit, das zu tun?

+0

Ich verstehe nicht die Notwendigkeit der x für x in Ihrem Fall. Warum benutzt du nicht einfach alle = [t [1] für t in Tests? – luc

+0

'[t [1] für t in Tests]' gibt eine Liste von Tupeln zurück. '[x für t in Tests für x in t [1]]' ist eine flache Liste (Verkettung dieser Tupel). –

Antwort

15

Es sollte anders umgehen:

all = [x for t in tests for x in t[1]] 
+0

Danke, ich frage mich, warum ich das selbst nicht getestet habe. :) Habe so viele verschiedene Wege ausprobiert. – Albert

+15

Ich denke, Pythons Wahl der Reihenfolge für mehrere "For" -Listen Verständnis war ein Fehler. Ich verstehe, dass es versucht, die Verwendung von geschachtelten for-Anweisungen zu replizieren, aber ich finde die Ergebnisse nicht lesbar und neigen dazu, es zu vermeiden. – bobince

+1

@bobince +1 völlig einverstanden, wenn die Absicht war, es mit dem normalen "für" kohärent zu halten, wäre ein besserer Weg gewesen, einfach den Block mit Klammern wie '[für x in l: f (x)]' zu umgeben ; aber in diesem Fall macht es mehr Sinn, die Verwendung und die Definition der Schleifenvariablen näher zu halten. – fortran

5

Im Zweifelsfall nicht Listenkomprehensionen verwenden.

Versuchen import this in Ihrer Python-Shell und lesen Sie die zweite Zeile:

Explicit is better than implicit 

Diese Art der Compoundierung von Listenkomprehensionen viel Python-Programmierer Puzzle wird so zumindest einen Kommentar hinzufügen zu erklären, dass Sie Zeichenfolgen zu entferne und flacht die verbleibende Liste ab.

Verwenden Sie Listenübersichten, wo sie klar und einfach zu verstehen sind, und insbesondere, wenn sie idiomatisch sind, d. H. Häufig verwendet, weil sie die effizienteste oder eleganteste Art sind, etwas auszudrücken. Zum Beispiel gibt this Python Idioms article das folgende Beispiel:

result = [3*d.Count for d in data if d.Count > 4] 

Es ist klar, einfach und unkompliziert. Das Verschachteln von Listenlisten ist nicht schlecht, wenn Sie auf die Formatierung achten und vielleicht einen Kommentar hinzufügen, weil die Klammern dem Leser helfen, den Ausdruck zu zerlegen. Aber die Lösung, die für dieses Problem akzeptiert wurde, ist meiner Meinung nach zu komplex und verwirrend. Es überschreitet die Grenzen und macht den Code für zu viele Menschen unlesbar. Es ist besser, mindestens eine Iteration in eine for-Schleife aufzurollen.

+0

Ich hoffe, ich verstehe dich falsch: * benutze keine List Comprehensions *. ** Benutze List Comprehensions, normale Operationen (wie map) sind auf diese Weise sehr klar ('[f (x) für x in Items]'). – u0b34a0f6ae

+1

Ich bevorzuge 'map (f, items)' zu '[f (x) für x in items]'. Es ist wie viele andere Python-Idiome - z.B. 'dict (zip (keys, values))' - Sobald Sie es einmal internalisiert haben, macht es die Verwendung von Code lesbarer, indem unnötige Entitäten eliminiert werden. –

+0

+1 für das Eintreten für KISS –

1

Das sieht für mich wie eine Reduzierung aus. Leider ist Python keinen syntaktischen Zucker bietet für reduzieren, so haben wir Lambda verwenden:

reduce(lambda x, y: x+y[1], tests, []) 
2

Wenn alles, was Sie tun, einige Listen fügen zusammen, versucht, die Summe gebautet, [] als Startwert verwendet:

all = sum((t[1] for t in tests), []) 
Verwandte Themen