Gibt es integrierte Methoden, die Teil von Listen sind, die mir den ersten und letzten Index eines Werts geben würden, wie zum Beispiel:
verts.IndexOf(12.345)
verts.LastIndexOf(12.345)
Gibt es integrierte Methoden, die Teil von Listen sind, die mir den ersten und letzten Index eines Werts geben würden, wie zum Beispiel:
verts.IndexOf(12.345)
verts.LastIndexOf(12.345)
Antworten:
Sequenzen haben eine Methode, index(value)
die den Index des ersten Auftretens zurückgibt - in Ihrem Fall wäre dies verts.index(value)
.
Sie können es ausführen verts[::-1]
, um den letzten Index herauszufinden. Hier wäre daslen(verts) - 1 - verts[::-1].index(value)
Wenn Sie nach dem Index des letzten Auftretens von myvalue
in suchen mylist
:
len(mylist) - mylist[::-1].index(myvalue) - 1
ValueError
wenn myvalue
nicht vorhanden in mylist
.
Python-Listen verfügen über die index()
Methode, mit der Sie die Position des ersten Auftretens eines Elements in einer Liste ermitteln können. Beachten Sie, dass dies list.index()
ausgelöst wird, ValueError
wenn das Element nicht in der Liste vorhanden ist. Daher müssen Sie es möglicherweise in try
/ einschließen except
:
try:
idx = lst.index(value)
except ValueError:
idx = None
Mit der folgenden Funktion können Sie die Position des letzten Auftretens eines Elements in einer Liste effizient ermitteln (dh ohne eine umgekehrte Zwischenliste zu erstellen):
def rindex(lst, value):
for i, v in enumerate(reversed(lst)):
if v == value:
return len(lst) - i - 1 # return the index in the original list
return None
print(rindex([1, 2, 3], 3)) # 2
print(rindex([3, 2, 1, 3], 3)) # 3
print(rindex([3, 2, 1, 3], 4)) # None
Vielleicht die zwei effizientesten Wege, um den letzten Index zu finden :
def rindex(lst, value):
lst.reverse()
i = lst.index(value)
lst.reverse()
return len(lst) - i - 1
def rindex(lst, value):
return len(lst) - operator.indexOf(reversed(lst), value) - 1
Beide benötigen nur O (1) zusätzlichen Platz und die beiden direkten Umkehrungen der ersten Lösung sind viel schneller als das Erstellen einer Umkehrkopie. Vergleichen wir es mit den anderen zuvor veröffentlichten Lösungen:
def rindex(lst, value):
return len(lst) - lst[::-1].index(value) - 1
def rindex(lst, value):
return len(lst) - next(i for i, val in enumerate(reversed(lst)) if val == value) - 1
Benchmark-Ergebnisse, meine Lösungen sind die roten und grünen:
Dies dient zum Suchen einer Nummer in einer Liste mit einer Million Nummern. Die x-Achse steht für die Position des gesuchten Elements: 0% bedeutet, dass es am Anfang der Liste steht, 100% bedeutet, dass es am Ende der Liste steht. Alle Lösungen sind am Standort zu 100% am schnellstenreversed
Lösungen so gut wie keine Zeit dafür benötigen, die Double-Reverse-Lösung etwas Zeit in Anspruch nimmt und die Reverse-Kopie viel Zeit in Anspruch nimmt.
Ein genauerer Blick auf das rechte Ende:
Am Standort 100% verbringen die Reverse-Copy-Lösung und die Double-Reverse-Lösung ihre ganze Zeit mit den Umkehrungen (index()
erfolgt sofort). Wir sehen also, dass die beiden vorhandenen Umkehrungen etwa siebenmal so schnell sind wie das Erstellen der Umkehrkopie.
Das obige war mit lst = list(range(1_000_000, 2_000_001))
, das die int-Objekte so ziemlich sequentiell im Speicher erstellt, was extrem cache-freundlich ist. Machen wir es noch einmal, nachdem wir die Liste mit gemischt haben random.shuffle(lst)
(wahrscheinlich weniger realistisch, aber interessant):
Wie erwartet wurde alles viel langsamer. Die Reverse-Copy-Lösung leidet am meisten. Mit 100% dauert sie jetzt etwa 32-mal (!) So lange wie die Double-Reverse-Lösung. Und die enumerate
-Lösung ist jetzt erst nach Standort 98% die zweitschnellste.
Insgesamt gefällt mir die operator.indexOf
Lösung am besten, da sie die schnellste für die letzte Hälfte oder das letzte Viertel aller Standorte ist. Dies sind möglicherweise die interessanteren Standorte, wenn Sie dies tatsächlich tunrindex
etwas . Und es ist nur ein bisschen langsamer als die Double-Reverse-Lösung an früheren Standorten.
Alle Benchmarks mit CPython 3.9.0 64-Bit unter Windows 10 Pro 1903 64-Bit.
Diese Methode kann optimiert werden als oben
def rindex(iterable, value):
try:
return len(iterable) - next(i for i, val in enumerate(reversed(iterable)) if val == value) - 1
except StopIteration:
raise ValueError
s.index(x[, i[, j]])
Index des ersten Auftretens von x in s (am oder nach dem Index i und vor dem Index j)