Die list.index(x)
Funktion gibt den Index in der Liste des ersten Elements zurück, dessen Wert ist x
.
Gibt es eine Funktion, list_func_index()
ähnlich der index()
Funktion, die eine Funktion hat f()
, als Parameter? Die Funktion f()
wird für jedes Element e
der Liste ausgeführt, bis sie f(e)
zurückgegeben wird True
. Dann list_func_index()
gibt den Index von e
.
Codeweise:
>>> def list_func_index(lst, func):
for i in range(len(lst)):
if func(lst[i]):
return i
raise ValueError('no element making func True')
>>> l = [8,10,4,5,7]
>>> def is_odd(x): return x % 2 != 0
>>> list_func_index(l,is_odd)
3
Gibt es eine elegantere Lösung? (und ein besserer Name für die Funktion)
map(f, seq)
anstelle von[f(x) for x in seq]
ist. Mit anderen Worten, es ist idiomatisch. Und wie bei anderen Redewendungen ist es nicht einfach, bis es Teil Ihres Wortschatzes ist.StopIteration
wenn die Endbedingung möglicherweise nicht erfüllt ist.next
Akzeptiert ein zweites Argument, das im Falle einer Nichtübereinstimmung zurückgegeben wird, anstatt zu erhöhenStopIteration
.Eine Möglichkeit ist die integrierte Aufzählungsfunktion :
def index_of_first(lst, pred): for i,v in enumerate(lst): if pred(v): return i return None
Es ist typisch, eine Funktion wie die, die Sie als "Prädikat" beschreiben, zu bezeichnen. es gibt für eine Frage wahr oder falsch zurück. Deshalb nenne ich es
pred
in meinem Beispiel.Ich denke auch, dass es besser wäre, zurückzukehren
None
, da dies die eigentliche Antwort auf die Frage ist. Der Anrufer kannNone
bei Bedarf wählen , ob er explodieren möchte.quelle
@ Pauls akzeptierte Antwort ist am besten, aber hier ist eine kleine Variante des Querdenkens, hauptsächlich zu Vergnügungs- und Unterrichtszwecken ...:
>>> class X(object): ... def __init__(self, pred): self.pred = pred ... def __eq__(self, other): return self.pred(other) ... >>> l = [8,10,4,5,7] >>> def is_odd(x): return x % 2 != 0 ... >>> l.index(X(is_odd)) 3
Im Wesentlichen besteht
X
der Zweck darin, die Bedeutung von "Gleichheit" von der normalen in "erfüllt dieses Prädikat" zu ändern, wodurch die Verwendung von Prädikaten in allen Arten von Situationen ermöglicht wird, die als Überprüfung auf Gleichheit definiert sind - zum Beispiel würde dies der Fall sein Sie können auch anstelle desif any(is_odd(x) for x in l):
kürzerenif X(is_odd) in l:
und so weiter codieren .Lohnt es sich zu benutzen? Nicht, wenn ein expliziterer Ansatz wie der von @Paul genauso praktisch ist (insbesondere, wenn die neue, glänzende integrierte
next
Funktion anstelle der älteren, weniger geeigneten.next
Methode verwendet wird, wie ich in einem Kommentar zu dieser Antwort vorschlage). Es gibt jedoch auch andere Situationen, in denen dies (oder andere Varianten der Idee "die Bedeutung von Gleichheit optimieren" und möglicherweise andere Komparatoren und / oder Hashing) angemessen sein können. Meistens wissenswert über die Idee, um zu vermeiden, dass man sie eines Tages von Grund auf neu erfinden muss ;-).quelle
Satisfies
, ein guter Name dafür ist.Keine einzige Funktion, aber Sie können es ziemlich einfach tun:
>>> test = lambda c: c == 'x' >>> data = ['a', 'b', 'c', 'x', 'y', 'z', 'x'] >>> map(test, data).index(True) 3 >>>
Wenn Sie nicht die gesamte Liste auf einmal auswerten möchten, können Sie itertools verwenden, aber es ist nicht so hübsch:
>>> from itertools import imap, ifilter >>> from operator import itemgetter >>> test = lambda c: c == 'x' >>> data = ['a', 'b', 'c', 'x', 'y', 'z'] >>> ifilter(itemgetter(1), enumerate(imap(test, data))).next()[0] 3 >>>
Nur die Verwendung eines Generatorausdrucks ist wahrscheinlich besser lesbar als
itertools
allerdings.Beachten Sie in Python3,
map
undfilter
geben Sie faule Iteratoren zurück, und Sie können einfach verwenden:from operator import itemgetter test = lambda c: c == 'x' data = ['a', 'b', 'c', 'x', 'y', 'z'] next(filter(itemgetter(1), enumerate(map(test, data))))[0] # 3
quelle
Eine Variation von Alex 'Antwort. Auf diese Weise müssen
X
Sie nicht jedes Mal eingeben, wenn Sie einis_odd
Prädikat verwenden möchten>>> class X(object): ... def __init__(self, pred): self.pred = pred ... def __eq__(self, other): return self.pred(other) ... >>> L = [8,10,4,5,7] >>> is_odd = X(lambda x: x%2 != 0) >>> L.index(is_odd) 3 >>> less_than_six = X(lambda x: x<6) >>> L.index(less_than_six) 2
quelle
Sie könnten dies mit einem Listenverständnis tun:
l = [8,10,4,5,7] filterl = [a for a in l if a % 2 != 0]
Dann gibt filterl alle Mitglieder der Liste zurück, die den Ausdruck a% 2! = 0 erfüllen. Ich würde eine elegantere Methode sagen ...
quelle