Ich möchte das erste Element aus einer Liste erhalten, die einer Bedingung entspricht. Es ist wichtig, dass die resultierende Methode nicht die gesamte Liste verarbeitet, was sehr groß sein kann. Zum Beispiel ist die folgende Funktion ausreichend:
def first(the_iterable, condition = lambda x: True):
for i in the_iterable:
if condition(i):
return i
Diese Funktion könnte ungefähr so verwendet werden:
>>> first(range(10))
0
>>> first(range(10), lambda i: i > 3)
4
Ich kann mir jedoch keinen guten eingebauten Einzeiler vorstellen, mit dem ich das machen kann. Ich möchte diese Funktion nicht besonders kopieren, wenn ich nicht muss. Gibt es eine integrierte Möglichkeit, um den ersten Artikel zu erhalten, der einer Bedingung entspricht?
Antworten:
In Python 2.6 oder neuer:
Wenn Sie ausgelöst
StopIteration
werden möchten , wenn kein passendes Element gefunden wird:Wenn Sie möchten, dass
default_value
(z. B.None
) zurückgegeben wird:Beachten Sie, dass Sie in diesem Fall ein zusätzliches Klammerpaar um den Generatorausdruck benötigen - diese werden immer dann benötigt, wenn der Generatorausdruck nicht das einzige Argument ist.
Ich sehe, dass die meisten Antworten die
next
integrierten Antworten entschlossen ignorieren, und gehe daher aus mysteriösen Gründen davon aus, dass sie sich zu 100% auf Versionen 2.5 und älter konzentrieren - ohne das Problem mit der Python-Version zu erwähnen (aber dann sehe ich diese Erwähnung nicht in die Antworten, die das Eingebaute erwähnennext
, weshalb ich es für notwendig hielt, selbst eine Antwort zu geben - zumindest das Problem der "richtigen Version" wird auf diese Weise aufgezeichnet ;-).In 2.5 wird die
.next()
Methode der Iteratoren sofort ausgelöst,StopIteration
wenn der Iterator sofort beendet ist - dh für Ihren Anwendungsfall, wenn kein Element in der Iterierbarkeit die Bedingung erfüllt. Wenn Sie kümmern sich nicht (dh, wissen Sie , es muss mindestens ein zufriedenstellendes Element sein) , dann benutzen Sie einfach.next()
(am besten auf einem genexp, Linie für dienext
Einbau-in Python 2.6 und besser).Wenn Sie sich darum kümmern, scheint es am besten, Dinge in eine Funktion zu verpacken, wie Sie sie zuerst in Ihrem Q angegeben haben, und obwohl die von Ihnen vorgeschlagene Funktionsimplementierung in Ordnung ist, können Sie alternativ
itertools
einefor...: break
Schleife oder einen Genexp oder atry/except StopIteration
als Funktionskörper verwenden , wie verschiedene Antworten vorschlugen. In keiner dieser Alternativen steckt viel Mehrwert, daher würde ich mich für die sehr einfache Version entscheiden, die Sie zuerst vorgeschlagen haben.quelle
StopIteration
wenn kein Element gefunden wurdeStopIteration
ist wirklich nicht schön. Verwenden Sie besser eine Methode.Als wiederverwendbare, dokumentierte und getestete Funktion
Version mit Standardargument
@zorf hat eine Version dieser Funktion vorgeschlagen, bei der Sie einen vordefinierten Rückgabewert haben können, wenn die Iterable leer ist oder keine Elemente vorhanden sind, die der Bedingung entsprechen:
quelle
StopIteration
ist die kanonische Ausnahme "out of elements" in Python. Ich sehe kein Problem damit, dass es geworfen wird. Ich würde wahrscheinlich den Standardwert "None" verwenden, der als Standardparameter an die Funktion übergeben werden kann.Verdammte Ausnahmen!
Ich liebe diese Antwort . Da jedoch
next()
eineStopIteration
Ausnahme ausgelöst wird, wenn keine Elemente vorhanden sind, würde ich das folgende Snippet verwenden, um eine Ausnahme zu vermeiden:Zum Beispiel,
Wird eine
StopIteration
Ausnahme auslösen;quelle
Ähnlich wie bei der Verwendung
ifilter
können Sie einen Generatorausdruck verwenden:In beiden Fällen möchten Sie wahrscheinlich jedoch fangen
StopIteration
, falls keine Elemente Ihre Bedingung erfüllen.Technisch gesehen könnten Sie so etwas tun:
Es würde vermeiden, einen
try/except
Block machen zu müssen. Aber das scheint irgendwie dunkel und missbräuchlich für die Syntax.quelle
for foo in genex: break
ist nur eine Möglichkeit,foo = next(genex)
ohne die Zuordnung klar zu machen, und mit der Ausnahme, dass sie ausgelöst wird, wenn die Operation keinen Sinn ergibt, wenn sie gequetscht wird. In Python ist es normalerweise eine schlechte Sache, einen Fehlercode zu erhalten, anstatt eine Ausnahme abzufangen.Der effizienteste Weg in Python 3 ist einer der folgenden (anhand eines ähnlichen Beispiels):
Mit "Verständnis" -Stil:
WARNUNG : Der Ausdruck funktioniert auch mit Python 2, wird jedoch im Beispiel verwendet
range
, das ein iterierbares Objekt in Python 3 anstelle einer Liste wie Python 2 zurückgibt (wenn Sie ein iterierbares Objekt in Python 2 erstellen möchten, verwenden Siexrange
stattdessen).Beachten Sie, dass der Ausdruck es vermeidet, eine Liste im Verständnisausdruck
next([i for ...])
zu erstellen, was dazu führen würde, dass eine Liste mit allen Elementen erstellt wird, bevor die Elemente gefiltert werden, und dass die gesamten Optionen verarbeitet werden, anstatt die Iteration einmal zu stoppeni == 1000
.Mit "funktionalem" Stil:
WARNUNG : Dies funktioniert in Python 2 nicht, selbst wenn es
range
durchxrange
Due ersetzt wird,filter
das eine Liste anstelle eines Iterators (ineffizient) erstelltnext
Funktion funktioniert nur mit Iteratoren.Standardwert
Wie in anderen Antworten erwähnt, müssen Sie der Funktion einen zusätzlichen Parameter hinzufügen,
next
wenn Sie eine Ausnahme vermeiden möchten, die ausgelöst wird, wenn die Bedingung nicht erfüllt ist."funktionaler" Stil:
"Verständnis" -Stil:
Bei diesem Stil müssen Sie den Verständnisausdruck mit umgeben
()
, um Folgendes zu vermeidenSyntaxError: Generator expression must be parenthesized if not sole argument
:quelle
Ich würde das schreiben
quelle
i > 3
solltex > 3
in Ihrem Beispiel seinDas
itertools
Modul enthält eine Filterfunktion für Iteratoren. Das erste Element des gefilterten Iterators kann durch Aufrufen erhalten werdennext()
:quelle
i
)filter
und (i
)map
können in Fällen sinnvoll sein, in denen die angewendeten Funktionen bereits vorhanden sind. In einer solchen Situation ist es jedoch viel sinnvoller, nur einen Generatorausdruck zu verwenden.Für ältere Versionen von Python, in denen die nächste integrierte Version nicht vorhanden ist:
quelle
Durch die Nutzung
Man kann den Zustand des Wertes des ersten Elements in the_iterable überprüfen und seinen Index erhalten, ohne alle Elemente in the_iterable auswerten zu müssen .
Der vollständige zu verwendende Ausdruck ist
Hier nimmt first_index den Wert des ersten Werts an, der in dem oben diskutierten Ausdruck identifiziert wurde.
quelle
Diese Frage hat bereits gute Antworten. Ich addiere nur meine zwei Cent, weil ich hier gelandet bin, um eine Lösung für mein eigenes Problem zu finden, das dem OP sehr ähnlich ist.
Wenn Sie mithilfe von Generatoren den INDEX des ersten Elements ermitteln möchten, das einem Kriterium entspricht, können Sie einfach Folgendes tun:
quelle
Sie können die
argwhere
Funktion auch in Numpy verwenden. Zum Beispiel:i) Finde das erste "l" in "helloworld":
ii) Finden Sie die erste Zufallszahl> 0,1
iii) Finden Sie die letzte Zufallszahl> 0,1
quelle
In Python 3:
In Python 2.6:
EDIT: Ich dachte, es wäre offensichtlich, aber anscheinend nicht: Stattdessen
None
können Sie eine Funktion (oder alambda
) mit einer Überprüfung auf die Bedingung übergeben:quelle
Einzeiler:
Wenn Sie nicht sicher sind, ob ein Element gemäß den Kriterien gültig ist, sollten Sie dies einschließen,
try/except
da[0]
dies eine auslösen kannIndexError
.quelle