Gibt es eine einfache Möglichkeit, eine Liste von iterables mit einer Liste Verständnis zu glätten, oder in Ermangelung dessen, was würden Sie alle betrachten, um den besten Weg zu glätten eine flache Liste wie diese, Ausgleich Leistung und Lesbarkeit?
Ich habe versucht, eine solche Liste mit einem verschachtelten Listenverständnis zu glätten, etwa so:
[image for image in menuitem for menuitem in list_of_menuitems]
Aber ich gerate in Schwierigkeiten durch die NameError
Vielfalt dort, weil die name 'menuitem' is not defined
. Nachdem ich gegoogelt und mich auf Stack Overflow umgesehen hatte, erhielt ich die gewünschten Ergebnisse mit einem reduce
Erklärung:
reduce(list.__add__, map(lambda x: list(x), list_of_menuitems))
Aber diese Methode ist ziemlich unleserlich, denn ich brauche die list(x)
Aufruf dort, weil x ein Django ist QuerySet
Objekt.
Schlussfolgerung :
Vielen Dank an alle, die zu dieser Frage beigetragen haben. Hier ist eine Zusammenfassung von dem, was ich gelernt habe. Ich mache dies auch zu einem Gemeinschafts-Wiki, falls andere diese Beobachtungen ergänzen oder korrigieren möchten.
Meine ursprüngliche Aussage zur Reduzierung ist redundant und sollte besser so formuliert werden:
>>> reduce(list.__add__, (list(mi) for mi in list_of_menuitems))
Dies ist die korrekte Syntax für ein verschachteltes Listenverständnis (Brillante Zusammenfassung dF !):
>>> [image for mi in list_of_menuitems for image in mi]
Aber keine dieser Methoden ist so effizient wie die Verwendung von itertools.chain
:
>>> from itertools import chain
>>> list(chain(*list_of_menuitems))
Und wie @cdleary bemerkt, ist es wahrscheinlich besser, die Magie des Operators * zu vermeiden, indem man chain.from_iterable
etwa so:
>>> chain = itertools.chain.from_iterable([[1,2],[3],[5,89],[],[6]])
>>> print(list(chain))
>>> [1, 2, 3, 5, 89, 6]
31 Stimmen
Ich verstehe nicht, warum alle map(lambda x: list(x), other) verwenden - ist das nicht gleichbedeutend mit map(list, other)? Das list builtin ist aufrufbar...
0 Stimmen
Es ist gleichwertig. Glücklicherweise hat Prairie Dogg erkannt, dass dieser Code hässlich ist :)
0 Stimmen
Ach ja, ich sehe, dass Sie in Ihrer Antwort darauf hingewiesen haben, @recursive. Entschuldigung für die Redundanz! :-)
2 Stimmen
@recursive: Ja, ich bin wirklich rot geworden, nachdem du mich darauf hingewiesen hast, wie viele Dinge in meiner Erklärung zur Reduzierung redundant waren. Ich habe auf jeden Fall eine Menge aus dieser Frage gelernt, also vielen Dank an alle!
0 Stimmen
Ich lerne jetzt schon eine Weile Ruby und hatte gerade die Gelegenheit, ein Ruby Idiom für ein ähnliches Problem zu verwenden. FWIW: [[1,2],[3],[5,89],[],[6]].flatten -> [1, 2, 3, 5, 89, 6]
1 Stimmen
Reduce(list.__add__, (list(mi.image_set.all()) for mi in list_of_menuitems)) ist nicht korrekt für den Fall, dass alle Listen leer sind. Es sollte reduce(list.__add__, (list(mi.image_set.all()) for mi in list_of_menuitems), []) lauten.
1 Stimmen
Diese Frage machte stackoverflow.com/q/952914/1206998 als dupliziert geschlossen. Allerdings ist es viel weniger klar wegen all der django irrelevant Zeug. Sollte es neu geschrieben werden?
0 Stimmen
"Aber ich bekomme dort Probleme der Sorte NameError, weil der Name 'menuitem' nicht definiert ist." Das Problem bei diesem Ansatz ist einfach, dass die
for
Die Klauseln sind in der falschen Reihenfolge. Ich habe einen weiteren doppelten Link hinzugefügt, um die richtige Technik für diesen Ansatz zu erläutern.