Jungs. Ich versuche, die eleganteste Lösung für ein Problem zu finden, und frage mich, ob in Python etwas für das integriert ist, was ich versuche.
Was ich tue ist das. Ich habe eine Liste A
und eine Funktion, f
die ein Element aufnimmt und eine Liste zurückgibt. Ich kann ein Listenverständnis verwenden, um alles A
so umzuwandeln .
[f(a) for a in A]
Dies gibt jedoch eine Liste von Listen zurück.
[a1,a2,a3] => [[b11,b12],[b21,b22],[b31,b32]]
Was ich wirklich will, ist, die abgeflachte Liste zu bekommen;
[b11,b12,b21,b22,b31,b32]
Jetzt haben es andere Sprachen; Es wird traditionell flatmap
in funktionalen Programmiersprachen aufgerufen , und .Net nennt es SelectMany
. Hat Python etwas Ähnliches? Gibt es eine gute Möglichkeit, eine Funktion einer Liste zuzuordnen und das Ergebnis zu reduzieren?
Das eigentliche Problem, das ich zu lösen versuche, ist das folgende; Beginnen Sie mit einer Liste von Verzeichnissen und suchen Sie alle Unterverzeichnisse. damit;
import os
dirs = ["c:\\usr", "c:\\temp"]
subs = [os.listdir(d) for d in dirs]
print subs
Aktuell gibt mir eine Liste von Listen, aber ich möchte wirklich eine Liste.
quelle
[ item for list in listoflists for item in list ]
>>> from functools import reduce >>> listOfLists = [[1, 2],[3, 4, 5], [6]] >>> reduce(list.__add__, listOfLists) [1, 2, 3, 4, 5, 6]
Ich vermute, die itertools-Lösung ist effizienter als diese, aber das fühlt sich sehr pythonisch an.
In Python 2 wird vermieden, dass eine Bibliothek nur für eine einzelne Listenoperation importiert werden muss (da dies
reduce
eine integrierte Funktion ist).quelle
reduce
, ist espandas
,scipy
oderfunctools
?functools
Version dieselbe.Eine gute Antwort finden Sie in den Rezepten von itertools:
def flatten(listOfLists): return list(chain.from_iterable(listOfLists))
(Hinweis: erfordert Python 2.6+)
quelle
Die vorgeschlagene Frage
flatmap
. Einige Implementierungen werden vorgeschlagen, aber möglicherweise müssen keine Zwischenlisten erstellt werden. Hier ist eine Implementierung, die auf Iteratoren basiert.def flatmap(func, *iterable): return itertools.chain.from_iterable(map(func, *iterable)) In [148]: list(flatmap(os.listdir, ['c:/mfg','c:/Intel'])) Out[148]: ['SPEC.pdf', 'W7ADD64EN006.cdr', 'W7ADD64EN006.pdf', 'ExtremeGraphics', 'Logs']
Verwenden Sie
itertools.map
in Python 2.x anstelle vonmap
.quelle
Sie könnten einfach das Unkomplizierte tun:
subs = [] for d in dirs: subs.extend(os.listdir(d))
quelle
Sie können Listen mit dem normalen Additionsoperator verketten:
>>> [1, 2] + [3, 4] [1, 2, 3, 4]
Die integrierte Funktion
sum
fügt die Zahlen in einer Sequenz hinzu und kann optional von einem bestimmten Wert ausgehen:>>> sum(xrange(10), 100) 145
Kombinieren Sie das Obige, um eine Liste von Listen zu reduzieren:
>>> sum([[1, 2], [3, 4]], []) [1, 2, 3, 4]
Sie können jetzt Folgendes definieren
flatmap
:>>> def flatmap(f, seq): ... return sum([f(s) for s in seq], []) ... >>> flatmap(range, [1,2,3]) [0, 0, 1, 0, 1, 2]
Bearbeiten: Ich habe gerade die Kritik in den Kommentaren für eine andere Antwort gesehen und ich denke, es ist richtig, dass Python mit dieser Lösung unnötig viele kleinere Listen erstellen und Müll sammeln wird. Das Beste, was man dazu sagen kann, ist, dass es sehr einfach und prägnant ist, wenn man an funktionale Programmierung gewöhnt ist :-)
quelle
import itertools x=[['b11','b12'],['b21','b22'],['b31']] y=list(itertools.chain(*x)) print y
itertools funktionieren ab python2.3 und höher
quelle
subs = [] map(subs.extend, (os.listdir(d) for d in dirs))
(aber Ants 'Antwort ist besser; +1 für ihn)
quelle
Sie könnten es so versuchen
itertools.chain()
:import itertools import os dirs = ["c:\\usr", "c:\\temp"] subs = list(itertools.chain(*[os.listdir(d) for d in dirs])) print subs
itertools.chain()
Gibt einen Iterator zurück, daher die Übergabe anlist()
.quelle
Google brachte mir die nächste Lösung:
def flatten(l): if isinstance(l,list): return sum(map(flatten,l)) else: return l
quelle
def flat_list(arr): send_back = [] for i in arr: if type(i) == list: send_back += flat_list(i) else: send_back.append(i) return send_back
quelle
Sie können Pyxtension verwenden :
from pyxtension.streams import stream stream([ [1,2,3], [4,5], [], [6] ]).flatMap() == range(7)
quelle
If listA=[list1,list2,list3] flattened_list=reduce(lambda x,y:x+y,listA)
Das wird es tun.
quelle
+
Operator zwischen zwei Listen ist O (n + m)