Was ist der kürzeste Weg, um die Anzahl der Elemente in einem generator/iterator?
Wenn ich die Anzahl der Elemente in einer durchsuchbar, ohne dass man sich über die Elemente selbst, was wäre die pythonic Weg zu bekommen? Jetzt würde ich definieren
def ilen(it):
return sum(itertools.imap(lambda _: 1, it)) # or just map in Python 3
aber ich verstehe lambda
ist in der Nähe nicht als schädlich, und lambda _: 1
ist sicherlich nicht schön.
(Der use-case-dieser zählt die Anzahl der Zeilen in einer text-Datei ein regex-matching, d.h. grep -c
.)
InformationsquelleAutor der Frage Fred Foo | 2011-03-21
Du musst angemeldet sein, um einen Kommentar abzugeben.
Der übliche Weg ist
InformationsquelleAutor der Antwort Sven Marnach
Methode, die bedeutend schneller als
sum(1 for i in it)
wenn die iterierbar kann lang sein (und nicht bedeutend langsamer, wenn die iterierbar ist kurz), während die Aufrechterhaltung der Feste Speicher-overhead Verhalten (im Gegensatz zulen(list(it))
) zu vermeiden, tauschen Prügel und Umverteilung overhead für größere Eingänge:Wie
len(list(it))
führt es die Schleife im C-code auf CPython (deque
count
undzip
sind alle implementiert in C); Vermeidung von byte-code-Ausführung pro loop ist in der Regel der Schlüssel zum Erfolg in CPython.Es ist überraschend schwer zu kommen mit einem fairen test-Fällen für den Vergleich von Leistung (
list
cheats mit__length_hint__
die wahrscheinlich nicht zur Verfügung stehen für beliebigen input iterables,itertools
Funktionen, die nicht__length_hint__
haben oft Besondere Betriebsmodi, die Arbeit schneller als der Wert, der zurückgegeben wird auf jede Schleife wird veröffentlicht befreit, bevor der nächste Wert angefordert wird, diedeque
mitmaxlen=0
tun wird). Der test-Fall, die ich verwendet wurde, erstellen Sie eine generator-Funktion, die dauern würde eine input-und eine C-level-generator, der fehlte besonderenitertools
Rückkehr Behälter Optimierungen oder__length_hint__
mit Python 3.3 istyield from
:Dann mit
ipython
%timeit
magic (anstelle der verschiedenen Konstanten für 100):Wenn die Eingabe nicht groß genug, dass
len(list(it))
würde dazu führen, Speicher Probleme, auf einem Linux-Rechner mit Python 3.5 x64, meine Lösung braucht etwa 50% länger alsdef ilen(it): return len(list(it))
unabhängig von der Eingabelänge.Für die kleinsten der Eingänge, die setup-Kosten zu nennen
deque
/zip
/count
/next
bedeutet, es nimmt mehr verschwindend, auf diese Weise alsdef ilen(it): sum(1 for x in it)
(etwa 200 ns mehr auf meinem Rechner mit der Länge 0 Eingabe, die eine 33% ige Steigerung gegenüber der einfachensum
Ansatz), aber für mehr Eingänge, läuft es in etwa der Hälfte der Zeit pro zusätzliches element; Länge 5 Eingänge, die den Kosten entspricht, und irgendwo in der Länge 50-100 Bereich, der anfängliche Aufwand ist zu vernachlässigen im Vergleich zu der echten Arbeit; diesum
Ansatz dauert etwa doppelt so lang.Grundsätzlich, wenn Speicher verwenden, Fragen oder inputs nicht begrenzt Größe und Sie kümmern sich um die Geschwindigkeit mehr als in der Kürze, diese Lösung verwenden. Wenn die Eingänge sind begrenzt und eher klein,
len(list(it))
ist wahrscheinlich am besten, und wenn Sie sind Grenzenlos, aber der Einfachheit/Bescheidenheit zählt, die Sie verwenden würdensum(1 for x in it)
.InformationsquelleAutor der Antwort ShadowRanger
Einen kurzen Weg:
Beachten Sie, dass, wenn Sie erzeugen eine viel der Elemente (sagen wir, zehntausend oder mehr), dann setzen Sie in eine Liste kann zu einem performance-Problem. Jedoch, dies ist ein einfacher Ausdruck der Vorstellung, wo die Leistung ist nicht die Materie für die meisten Fälle.
InformationsquelleAutor der Antwort Greg Hewgill
Ich mag die Kardinalität - Paket für diese, es ist sehr leicht, und der versucht, die schnellstmögliche Umsetzung zur Verfügung, je nach den durchsuchbar.
Verwendung:
InformationsquelleAutor der Antwort Erwin Mayer
more_itertools
ist ein third-party-Bibliothek, die eineilen
tool.pip install more_itertools
InformationsquelleAutor der Antwort pylang