432 Stimmen

Verflachen einer flachen Liste in Python

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! :-)

1voto

strpeter Punkte 2142

Eine einfache Alternative ist die Verwendung von numpy's Verkettung aber es wandelt den Inhalt in Float um:

import numpy as np
print np.concatenate([[1,2],[3],[5,89],[],[6]])
# array([  1.,   2.,   3.,   5.,  89.,   6.])
print list(np.concatenate([[1,2],[3],[5,89],[],[6]]))
# [  1.,   2.,   3.,   5.,  89.,   6.]

1voto

YPCrumble Punkte 23372

Der einfachste Weg, dies entweder in Python 2 oder 3 zu erreichen, ist die Verwendung der morph Bibliothek mit pip install morph .

Der Code lautet:

import morph

list = [[1,2],[3],[5,89],[],[6]]
flattened_list = morph.flatten(list)  # returns [1, 2, 3, 5, 89, 6]

1 Stimmen

"am einfachsten" ist ein starkes Wort

0 Stimmen

@cfi Die von Ihnen vorgeschlagene Antwort funktioniert nicht in Python 2 und aus den Kommentaren geht hervor, dass es nicht einmal eine akzeptable Antwort in Python 3 ist. Die Morph-Bibliothek ist eine einfache Ein-Funktions-Lösung, wie man sie in lodash für Javascript hat. Auf jeden Fall habe ich meine Antwort bearbeitet, um klarzustellen, dass es die einfachste Lösung ist, die in Python 2 und 3 funktioniert.

0 Stimmen

Ich bitte um Entschuldigung. Mein Kommentar war ein wenig faul, zumal Sie mich auf meinen eigenen Kommentar in dem anderen Beitrag hingewiesen haben. Ich wollte damit sagen, dass "am einfachsten" ein Superlativ ist, der schwer zu erreichen ist. Ihr Vorschlag erfordert eine externe Bibliothek, die für einige schwer zu installieren sein könnte (sogar mit venv und so). Da es in der Frage um "flache" Listen geht und um die "Balance zwischen Leistung und Lesbarkeit", könnte(!) Ihre Antwort bei der Lesbarkeit gewinnen. Aber diese ist leistungsfähiger und einfacher, da es keine Abhängigkeiten benötigt.

0voto

elyase Punkte 36724

En Python 3.4 werden Sie tun können:

[*innerlist for innerlist in outer_list]

1 Stimmen

Hm. Ich würde das zwar begrüßen, aber das wurde schon vor langer Zeit für Py3.0 diskutiert. Jetzt ist die PEP 448 ist da, aber immer noch im Modus "Entwurf". Die zugehörige Wanzenticket befindet sich noch in der "Patch-Review" mit einem noch unvollständigen Patch. Solange der Fehler nicht als "commited" markiert ist, wäre ich vorsichtig damit, mir Hoffnungen zu machen und zu sagen, dass man dazu in der Lage sein wird.

0 Stimmen

Ich verstehe, was du meinst, aber es wurde kürzlich auf der Kiwi PyCon 2013 von einem der Kernentwickler als "zur Veröffentlichung angenommen" in 3.4 angekündigt. Noch nicht 100% sicher, aber ich denke, sehr wahrscheinlich.

0 Stimmen

Hoffen wir beide, dass es nur an der Dokumentation liegt, die wie üblich bei sw vor jeder Veröffentlichung hinter dem Code zurückbleibt ;-)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X