Ich möchte auf idiomatische Weise das erste Element in einer Liste finden, das einem Prädikat entspricht.
Der aktuelle Code ist ziemlich hässlich:
[x for x in seq if predicate(x)][0]
Ich habe darüber nachgedacht, es zu ändern in:
from itertools import dropwhile
dropwhile(lambda x: not predicate(x), seq).next()
Aber es muss etwas eleganteres geben ... Und es wäre schön, wenn es einen None
Wert zurückgibt , anstatt eine Ausnahme auszulösen, wenn keine Übereinstimmung gefunden wird.
Ich weiß, ich könnte einfach eine Funktion definieren wie:
def get_first(predicate, seq):
for i in seq:
if predicate(i): return i
return None
Es ist jedoch geschmacklos, den Code mit solchen Dienstprogrammfunktionen zu füllen (und die Leute werden wahrscheinlich nicht bemerken, dass sie bereits vorhanden sind, sodass sie sich im Laufe der Zeit wiederholen), wenn es integrierte Funktionen gibt, die diese bereits bereitstellen.
Antworten:
So finden Sie das erste Element in einer Sequenz
seq
, die mit a übereinstimmtpredicate
:Oder (
itertools.ifilter
auf Python 2) :Es wird erhöht,
StopIteration
wenn es keine gibt.Um zurückzukehren,
None
wenn es kein solches Element gibt:Oder:
quelle
next
das verwendet wird, anstatt die Ausnahme auszulösen.next()
ist seit Python 2.6 verfügbar. Sie können die Seite " Neue Funktionen" lesen, um sich schnell mit den neuen Funktionen vertraut zu machen.seq.find(&method(:predicate))
oder noch prägnanter zum Beispiel Methoden zB:[1,1,4].find(&:even?)
ifilter
wurdefilter
in Python 3 umbenannt .Sie können einen Generatorausdruck mit einem Standardwert verwenden und dann
next
:Obwohl Sie für diesen Einzeiler Python> = 2.6 verwenden müssen.
In diesem recht beliebten Artikel wird dieses Problem weiter erläutert: Sauberste Python-Funktion zum Suchen in der Liste? .
quelle
Ich glaube nicht, dass an beiden Lösungen, die Sie in Ihrer Frage vorgeschlagen haben, etwas falsch ist.
In meinem eigenen Code würde ich es jedoch so implementieren:
Die Syntax mit
()
erstellt einen Generator, der effizienter ist als das gleichzeitige Generieren der gesamten Liste mit[]
.quelle
[]
Ihnen könnten Probleme auftreten, wenn der Iterator nie endet oder seine Elemente schwer zu erstellen sind, je später er wird ...'generator' object has no attribute 'next'
auf Python 3.Die Antwort von JF Sebastian ist am elegantesten, erfordert jedoch Python 2.6, wie fortran hervorhob.
Für Python-Version <2.6 ist hier das Beste, was ich mir vorstellen kann:
Wenn Sie später eine Liste benötigen (Liste behandelt die StopIteration) oder mehr als nur die erste, aber immer noch nicht alle benötigen, können Sie dies mit islice tun:
UPDATE: Obwohl ich persönlich eine vordefinierte Funktion namens first () verwende, die eine StopIteration abfängt und None zurückgibt, ist hier eine mögliche Verbesserung gegenüber dem obigen Beispiel: Vermeiden Sie die Verwendung von filter / ifilter:
quelle