Der beste Weg, dies zu tun, hängt davon ab, was Sie tun, wenn nichts gefunden wird. Selbst wenn wir list.find hätten , das eine -1 zurückgibt , müssten Sie immer noch testen, ob die i == -1und etwas unternehmen.
Raymond Hettinger
2
Raymond - es scheint nur an mir zu liegen, zu entscheiden, ob mein Code keine Indizes verarbeiten kann, anstatt die Ausnahme zu erzwingen. Aber dann lerne ich immer noch, wie man pythonisch ist ...
@yarin, wie ich in meiner Antwort klargestellt habe: Wenn Sie den Index nicht benötigen, ist das inSchlüsselwort genau das, was Sie brauchen. Aber wenn Sie das tun, hat Raymond meiner Meinung nach einen guten Punkt, und Ausnahmen sind der beste Weg, dies zu erreichen.
Nealmcb
Antworten:
93
Wenn es Ihnen egal ist, wo sich das passende Element befindet, verwenden Sie:
Vielen Dank, Raymond, fand dies die prägnanteste Antwort (Wiederum wurde die Standardeinstellung von -1 in Keine geändert, da -1 ein gültiger Listenindex ist)
Yarin
1
Danke Raymond, LBYL war eine neue Referenz für mich.
Burhan Khalid
14
Aber ist dieser Ansatz nicht viel langsamer als beim Laufen index()? Immerhin muss man zweimal suchen: einmal nach der Existenz und einmal nach dem Index. Aus diesem Grund ist C ++ Container nicht ein haben exists(), nur find().
Frans
9
Wie @frans sagte, erfordert dies zwei Suchvorgänge, aber hier ist eine andere Möglichkeit, die Arbeit in einem Durchgang zu i = next((i for i, t in enumerate(somelist) if x == t), None)
erledigen
@AXO Obwohl es sich um einen Durchgang handelt, wird es für integrierte Typen langsamer, da die Suche eher von Python als von C-Code durchgeführt wird.
Sie können also list verwenden und mit Ihrem index2 im Fehlerfall das zurückgeben, was Sie möchten.
Sie können es so verwenden:
l = mylist([1,2,3,4,5]) # This is the only difference with a real list
l.append(4) # l is a list.
l.index_withoutexception(19) # return -1 or what you want
Beachten Sie, dass dies einen Code beschädigen kann: type(l) == listist Falsehier.
Bfontaine
1
Auch - ich bin nicht positiv, aber es scheint mir, dass wenn das Ziel darin besteht, eine Ausnahme zu vermeiden (was teuer ist, wenn es häufig vorkommt), dies nicht erreicht wird. Es wird -1 zurückgegeben, aber intern wird immer noch eine Ausnahme ausgelöst, die immer noch kostspielig ist.
LogicOnAbstractions
6
TL; DR: Ausnahmen sind Ihr Freund und der beste Ansatz für die Frage, wie angegeben. Es ist einfacher, um Vergebung zu bitten als um Erlaubnis (EAFP)
Das OP stellte in einem Kommentar klar, dass es für ihren Anwendungsfall eigentlich nicht wichtig war, den Index zu kennen. Wie die akzeptierte Antwort vermerkt, x in somelistist die Verwendung die beste Antwort, wenn Sie sich nicht darum kümmern.
Aber ich gehe davon aus, dass es Ihnen wichtig ist , was der Index ist , wie die ursprüngliche Frage nahelegt . In diesem Fall muss ich feststellen, dass bei allen anderen Lösungen die Liste zweimal gescannt werden muss, was zu einer erheblichen Leistungsminderung führen kann.
Darüber hinaus schrieb der ehrwürdige Raymond Hettinger in einem Kommentar
Selbst wenn wir list.find hätten, das -1 zurückgibt, müssten Sie immer noch testen, ob i == -1 ist, und etwas unternehmen.
Ich werde also auf die Annahme in der ursprünglichen Frage zurückgreifen, dass Ausnahmen vermieden werden sollten. Ich schlage vor, dass Ausnahmen dein Freund sind. Sie sind nichts, vor dem man Angst haben muss, sie sind nicht ineffizient, und tatsächlich müssen Sie mit ihnen vertraut sein, um guten Code zu schreiben.
Daher denke ich, dass die beste Antwort darin besteht, einfach einen Try-außer-Ansatz zu verwenden:
try:
i = somelist.index(x)
except ValueError:
# deal with it
"damit umgehen " bedeutet nur, das zu tun, was Sie tun müssen: i auf einen Sentinel-Wert setzen, eine eigene Ausnahme auslösen, einem anderen Code-Zweig folgen usw.
So wahr! Ich dachte, ich hätte dieses Problem und dachte zuerst, eine der anderen Lösungen sei gut. Dann schaute ich noch einmal auf meinen Code und stellte fest, dass die Verwendung eines Versuchs ... außer schneller und natürlicher wäre, da ich mich natürlich noch damit befassen muss ...
nealmcb
1
Ich lache laut. Manchmal halten Einsichten nicht an. Ich habe gerade den obigen Kommentar abgegeben, ohne zu bemerken, dass ich die Antwort vor 2 Jahren überhaupt geschrieben hatte. Erst als ich versuchte, meine eigene Antwort abzustimmen, hat mich SO darauf
hingewiesen
Das ist absolut lustig!
T_M
4
Schreiben Sie eine Funktion, die das tut, was Sie brauchen:
deffind_in_iterable(x, iterable):for i, item in enumerate(iterable):
if item == x:
return i
returnNone
Wenn Sie nur wissen müssen, ob das Element vorhanden ist, nicht aber den Index, können Sie Folgendes verwenden in:
Danke - aber ich hatte auf etwas Vorverpacktes gehofft
Yarin
4
PS '-1' ist ein gültiger Listenindex - Sie müssen 'None' zurückgeben
Yarin
@Yarin: Der Grund, warum ich -1 gewählt habe, war, dass ich zum Beispiel mit vorhandenen Python-Redewendungen übereinstimmte 'abc'.find('x') == -1, aber Noneauch funktionieren würde. Ich werde meine Antwort aktualisieren.
Mark Byers
1
Ja, das ist seltsam, dass .find () das tut - scheint nicht mit den negativen Indizes von Python übereinzustimmen.
Im Grunde test()wird also der Index des Elements (zweiter Parameter) innerhalb der angegebenen Liste (erster Parameter) zurückgegeben, sofern er nicht gefunden wurde (in diesem Fall wird er zurückgegeben None, aber es kann alles sein, was Sie für geeignet halten).
Wenn es Ihnen egal ist, wo es sich in der Sequenz befindet, nur seine Anwesenheit, verwenden Sie den inOperator. Andernfalls schreiben Sie eine Funktion, die die Ausnahmebehandlung umgestaltet.
Ich habe eine Antwort veröffentlicht, die die Existenz mithilfe indes Index überprüft und schließlich zurückgibt, aber ich sehe, dass Sie diese Methode kennen und beschlossen haben, Ausnahmen zu behandeln, die möglicherweise ausgelöst werden. Meine Frage ist: Warum haben Sie sich für eine Ausnahme entschieden, anstatt zuerst die haystackExistenz zu überprüfen needle? Gibt es dafür einen Grund?
Tadeck
@Tadeck: Aufgrund der ungeschriebenen Python-Regel "Es ist einfacher, um Vergebung als um Erlaubnis zu bitten".
In diesem Beitrag geht es um die Array-Indizierung mit dem IndexError: list index out of rangeProblem, nicht um die hier beschriebene index()Methode mit dem ValueError: <value> is not in listProblem.
Nealmcb
0
Ich verwende gerne die List- Klasse von Web2py , die sich im Speichermodul des Gluon-Pakets befindet. Das Speichermodul bietet listenartige (List) und wörterbuchartige (Storage) Datenstrukturen, die keine Fehler auslösen, wenn ein Element nicht gefunden wird.
Laden Sie zuerst die Quelle von web2py herunter und kopieren Sie dann den Gluon-Paketordner in die Site-Pakete Ihrer Python-Installation.
Probieren Sie es jetzt aus:
>>> from gluon.storage import List
>>> L = List(['a','b','c'])
>>> print L(2)
c
>>> print L(3) #No IndexError!None
Beachten Sie, dass es sich auch wie eine normale Liste verhalten kann:
>>> print L[3]
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
l[3]
IndexError: list index out of range
i == -1
und etwas unternehmen.in
Schlüsselwort genau das, was Sie brauchen. Aber wenn Sie das tun, hat Raymond meiner Meinung nach einen guten Punkt, und Ausnahmen sind der beste Weg, dies zu erreichen.Antworten:
Wenn es Ihnen egal ist, wo sich das passende Element befindet, verwenden Sie:
found = x in somelist
Wenn Sie sich interessieren, verwenden Sie einen LBYL- Stil mit einem bedingten Ausdruck :
i = somelist.index(x) if x in somelist else None
quelle
index()
? Immerhin muss man zweimal suchen: einmal nach der Existenz und einmal nach dem Index. Aus diesem Grund ist C ++ Container nicht ein habenexists()
, nurfind()
.i = next((i for i, t in enumerate(somelist) if x == t), None)
eigenen Index für Liste implementieren?
class mylist(list): def index_withoutexception(self,i): try: return self.index(i) except: return -1
Sie können also list verwenden und mit Ihrem index2 im Fehlerfall das zurückgeben, was Sie möchten.
Sie können es so verwenden:
l = mylist([1,2,3,4,5]) # This is the only difference with a real list l.append(4) # l is a list. l.index_withoutexception(19) # return -1 or what you want
quelle
type(l) == list
istFalse
hier.TL; DR: Ausnahmen sind Ihr Freund und der beste Ansatz für die Frage, wie angegeben.
Es ist einfacher, um Vergebung zu bitten als um Erlaubnis (EAFP)
Das OP stellte in einem Kommentar klar, dass es für ihren Anwendungsfall eigentlich nicht wichtig war, den Index zu kennen. Wie die akzeptierte Antwort vermerkt,
x in somelist
ist die Verwendung die beste Antwort, wenn Sie sich nicht darum kümmern.Aber ich gehe davon aus, dass es Ihnen wichtig ist , was der Index ist , wie die ursprüngliche Frage nahelegt . In diesem Fall muss ich feststellen, dass bei allen anderen Lösungen die Liste zweimal gescannt werden muss, was zu einer erheblichen Leistungsminderung führen kann.
Darüber hinaus schrieb der ehrwürdige Raymond Hettinger in einem Kommentar
Ich werde also auf die Annahme in der ursprünglichen Frage zurückgreifen, dass Ausnahmen vermieden werden sollten. Ich schlage vor, dass Ausnahmen dein Freund sind. Sie sind nichts, vor dem man Angst haben muss, sie sind nicht ineffizient, und tatsächlich müssen Sie mit ihnen vertraut sein, um guten Code zu schreiben.
Daher denke ich, dass die beste Antwort darin besteht, einfach einen Try-außer-Ansatz zu verwenden:
try: i = somelist.index(x) except ValueError: # deal with it
"damit umgehen " bedeutet nur, das zu tun, was Sie tun müssen: i auf einen Sentinel-Wert setzen, eine eigene Ausnahme auslösen, einem anderen Code-Zweig folgen usw.
Dies ist ein Beispiel dafür, warum das Python-Prinzip Leichter um Vergebung als um Erlaubnis zu bitten (EAFP) sinnvoll ist, im Gegensatz zum Wenn-Dann-Sonst-Stil von Look before you leap (LBYL).
quelle
Schreiben Sie eine Funktion, die das tut, was Sie brauchen:
def find_in_iterable(x, iterable): for i, item in enumerate(iterable): if item == x: return i return None
Wenn Sie nur wissen müssen, ob das Element vorhanden ist, nicht aber den Index, können Sie Folgendes verwenden
in
:x in yourlist
quelle
'abc'.find('x') == -1
, aberNone
auch funktionieren würde. Ich werde meine Antwort aktualisieren.Ja da ist. Sie können z. mache etwas ähnliches:
test = lambda l, e: l.index(e) if e in l else None
was so funktioniert:
>>> a = ['a', 'b', 'c', 'g', 'c'] >>> test(a, 'b') 1 >>> test(a, 'c') 2 >>> test(a, 't') None
Im Grunde
test()
wird also der Index des Elements (zweiter Parameter) innerhalb der angegebenen Liste (erster Parameter) zurückgegeben, sofern er nicht gefunden wurde (in diesem Fall wird er zurückgegebenNone
, aber es kann alles sein, was Sie für geeignet halten).quelle
Wenn es Ihnen egal ist, wo es sich in der Sequenz befindet, nur seine Anwesenheit, verwenden Sie den
in
Operator. Andernfalls schreiben Sie eine Funktion, die die Ausnahmebehandlung umgestaltet.def inlist(needle, haystack): try: return haystack.index(needle) except ...: return -1
quelle
in
des Index überprüft und schließlich zurückgibt, aber ich sehe, dass Sie diese Methode kennen und beschlossen haben, Ausnahmen zu behandeln, die möglicherweise ausgelöst werden. Meine Frage ist: Warum haben Sie sich für eine Ausnahme entschieden, anstatt zuerst diehaystack
Existenz zu überprüfenneedle
? Gibt es dafür einen Grund?...
in derexcept ...:
Leitung.hoffe das hilft
lst= ','.join('qwerty').split(',') # create list i='a' #srch string lst.index(i) if i in lst else None
quelle
Es gibt keine integrierte Möglichkeit, das zu tun, was Sie tun möchten.
Hier ist ein guter Beitrag, der Ihnen helfen kann: Warum hat die Liste keine sichere "get" -Methode wie das Wörterbuch?
quelle
IndexError: list index out of range
Problem, nicht um die hier beschriebeneindex()
Methode mit demValueError: <value> is not in list
Problem.Ich verwende gerne die List- Klasse von Web2py , die sich im Speichermodul des Gluon-Pakets befindet. Das Speichermodul bietet listenartige (List) und wörterbuchartige (Storage) Datenstrukturen, die keine Fehler auslösen, wenn ein Element nicht gefunden wird.
Laden Sie zuerst die Quelle von web2py herunter und kopieren Sie dann den Gluon-Paketordner in die Site-Pakete Ihrer Python-Installation.
Probieren Sie es jetzt aus:
>>> from gluon.storage import List >>> L = List(['a','b','c']) >>> print L(2) c >>> print L(3) #No IndexError! None
Beachten Sie, dass es sich auch wie eine normale Liste verhalten kann:
>>> print L[3] Traceback (most recent call last): File "<pyshell#4>", line 1, in <module> l[3] IndexError: list index out of range
quelle
def __call__(self, idx, df=None): return self[idx] if 0<=idx<len(self) else df