it-swarm.com.de

Am besten mit list.index (möglicherweise nicht vorhanden) in Python umgehen?

Ich habe Code, der ungefähr so ​​aussieht:

thing_index = thing_list.index(thing)
otherfunction(thing_list, thing_index)

ok, das ist vereinfacht, aber Sie bekommen die Idee. Nun ist thing möglicherweise nicht wirklich in der Liste. In diesem Fall möchte ich -1 als thing_index übergeben. In anderen Sprachen würden Sie erwarten, dass index() zurückkehrt, wenn das Element nicht gefunden wurde. Tatsächlich wirft es eine ValueError.

Ich könnte das machen:

try:
    thing_index = thing_list.index(thing)
except ValueError:
    thing_index = -1
otherfunction(thing_list, thing_index)

Aber das fühlt sich schmutzig an und ich weiß nicht, ob ValueError aus einem anderen Grund angehoben werden könnte. Ich habe die folgende Lösung auf der Grundlage von Generatorfunktionen gefunden, die jedoch etwas komplex erscheint:

thing_index = ( [(i for i in xrange(len(thing_list)) if thing_list[i]==thing)] or [-1] )[0]

Gibt es einen saubereren Weg, um dasselbe zu erreichen? Nehmen wir an, die Liste ist nicht sortiert.

79
Draemon

Es ist nichts "schmutzig" bei der Verwendung der try-except-Klausel. Dies ist der pythonische Weg. ValueError wird nur von der .index-Methode ausgelöst, da dies der einzige Code ist, den Sie dort haben!

Um den Kommentar zu beantworten:
In Python ist es ist einfacher, um Vergebung zu bitten, als um Erlaubnis zu bitten philosophie ist etabliert, und noindex löst diese Art Fehler nicht für andere Probleme aus. Nicht, dass mir was einfällt. 

52
SilentGhost
thing_index = thing_list.index(elem) if elem in thing_list else -1

Eine Linie. Einfach. Keine Ausnahmen.

38
Emil Ivanov

Der dict-Typ hat eine get-Funktion . Wenn der Schlüssel nicht im Wörterbuch vorhanden ist, ist das 2. Argument für get der Wert, den es zurückgeben soll. Ebenso gibt es setdefault , das den Wert in der dict zurückgibt, wenn der Schlüssel vorhanden ist. Andernfalls wird der Wert entsprechend Ihrem Standardparameter festgelegt und der Standardparameter zurückgegeben.

Sie könnten den Typ list erweitern, um eine getindexdefault-Methode zu erhalten.

class SuperDuperList(list):
    def getindexdefault(self, elem, default):
        try:
            thing_index = self.index(elem)
            return thing_index
        except ValueError:
            return default

Was könnte dann verwendet werden:

mylist = SuperDuperList([0,1,2])
index = mylist.getindexdefault( 'asdf', -1 )
15
Ross Rogers

Es ist nichts falsch mit Ihrem Code, der ValueError verwendet. Hier ist noch ein Einzeiler, wenn Sie Ausnahmen vermeiden möchten:

thing_index = next((i for i, x in enumerate(thing_list) if x == thing), -1)
5
jfs

Diese Ausgabe ist eine Sprachphilosophie. In Java zum Beispiel gab es immer die Tradition, dass Ausnahmen eigentlich nur in "Ausnahmefällen" verwendet werden sollten, in denen Fehler aufgetreten sind, und nicht für flow control . Am Anfang war dies aus Gründen der Performance, da Java-Ausnahmen langsam waren, aber jetzt ist dies der akzeptierte Stil.

Im Gegensatz dazu hat Python immer Ausnahmen verwendet, um auf einen normalen Programmablauf hinzuweisen, wie das Erhöhen einer ValueError, wie wir hier besprechen. Es gibt nichts "Dreckiges" im Python-Stil und es gibt viele weitere, aus denen das kam. Ein noch häufigeres Beispiel ist StopIteration exception , das von der next()-Methode eines Iterators ausgelöst wird, um zu signalisieren, dass keine weiteren Werte vorhanden sind.

3
Tendayi Mawushe

Was ist mit diesem:

otherfunction(thing_collection, thing)

Anstatt etwas so implementierungsabhängiges wie einen Listenindex in einer Funktionsschnittstelle bereitzustellen, übergeben Sie die Sammlung und die Sache und lassen andere Funktionen sich mit dem "Test auf Mitgliedschaft" befassen. Wenn eine andere Funktion als sammlungsunabhängig geschrieben wird, beginnt sie wahrscheinlich mit:

if thing in thing_collection:
    ... proceed with operation on thing

was funktionieren wird, wenn thing_collection eine Liste, ein Tuple, ein Set oder ein Dikt ist.

Dies ist möglicherweise klarer als:

if thing_index != MAGIC_VALUE_INDICATING_NOT_A_MEMBER:

dies ist der Code, den Sie bereits in einer anderen Funktion haben.

1
PaulMcG

Wenn Sie dies häufig tun, ist es besser, es in einer Hilfsfunktion wegzurennen:

def index_of(val, in_list):
    try:
        return in_list.index(val)
    except ValueError:
        return -1 
0
Veneet Reddy

Ich habe das gleiche Problem mit der ".index ()" - Methode in Listen. Ich habe kein Problem mit der Tatsache, dass es eine Ausnahme auslöst, aber ich bin absolut nicht einverstanden mit der Tatsache, dass es sich um einen nicht beschreibenden ValueError handelt. Ich könnte verstehen, ob es ein IndexError gewesen wäre.

Ich kann sehen, warum die Rückgabe von "-1" ebenfalls ein Problem darstellt, da es sich um einen gültigen Index in Python handelt. Aber realistisch erwarte ich nie, dass eine ".index ()" - Methode eine negative Zahl zurückgibt.

Hier geht ein Einzeiler (ok, es ist eine ziemlich lange Zeile ...), geht die Liste genau einmal durch und gibt "Keine" zurück, wenn der Gegenstand nicht gefunden wird. Es wäre trivial, es umzuschreiben, um -1 zurückzugeben, falls Sie dies wünschen.

indexOf = lambda list, thing: \
            reduce(lambda acc, (idx, elem): \
                   idx if (acc is None) and elem == thing else acc, list, None)

Wie benutzt man:

>>> indexOf([1,2,3], 4)
>>>
>>> indexOf([1,2,3], 1)
0
>>>
0
haavee

Was ist mit so:

temp_inx = (L + [x]).index(x) 
inx = temp_inx if temp_inx < len(L) else -1
0
Jie Xiong

Was ist damit ???? :

li = [1,2,3,4,5] # create list 

li = dict(Zip(li,range(len(li)))) # convert List To Dict 
print( li ) # {1: 0, 2: 1, 3: 2, 4:3 , 5: 4}
li.get(20) # None 
li.get(1)  # 0 
0
Alaa Akiel