Wenn Sie tatsächlich nur einzelne Buchstaben verwenden, wie in Ihrem Beispiel gezeigt, str.rindex
würde dies problemlos funktionieren. Dies löst eine ValueError
Fehlerklasse aus, die vorhanden ist, wenn es kein solches Element gibt list.index
. Demo:
>>> li = ["a", "b", "a", "c", "x", "d", "a", "6"]
>>> ''.join(li).rindex('a')
6
Für den allgemeineren Fall könnten Sie list.index
auf der umgekehrten Liste verwenden:
>>> len(li) - 1 - li[::-1].index('a')
6
Durch das Schneiden hier wird eine Kopie der gesamten Liste erstellt. Das ist in Ordnung für kurze Listen, aber für den Fall, dass li
es sehr groß ist, kann die Effizienz mit einem faulen Ansatz besser sein:
def list_rindex(li, x):
for i in reversed(range(len(li))):
if li[i] == x:
return i
raise ValueError("{} is not in list".format(x))
Einzeiler-Version:
next(i for i in reversed(range(len(li))) if li[i] == 'a')
len(li) - next(i for i, v in enumerate(reversed(li), 1) if v == 'a')
ist ein wenig schneller für michstr.rindex()
einen Grund, warum es keinen gibtlist.rindex()
?range(len(li)-1, -1, -1)
entwederreversed(range(len(li)))
oderrange(len(li))[::-1]
(sie sind im Gegensatz zu den meisten Vergleichen zwischenreversed
und dem Umkehr-Slice auch ungefähr gleichwertig ; modernes Py3range
kann umgekehrt geschnitten werden, um ein anderes Faulpelz zu machenrange
, das rückwärts läuft, also ist es gleichermaßen performant). Sieht so aus, als wäre ich mit dem ersteren gegangen.next(len(a)-i-1 for i, x in enumerate(reversed(a)) if x == 3)
Ein Einzeiler, der Ignacios ähnelt, nur etwas einfacher / klarer wäre
max(loc for loc, val in enumerate(li) if val == 'a')
Es scheint mir sehr klar und pythonisch: Sie suchen nach dem höchsten Index, der einen übereinstimmenden Wert enthält. Keine Nexts, Lambdas, Reverseds oder Itertools erforderlich.
quelle
Viele der anderen Lösungen erfordern das Durchlaufen der gesamten Liste. Das tut nicht.
def find_last(lst, elm): gen = (len(lst) - 1 - i for i, v in enumerate(reversed(lst)) if v == elm) return next(gen, None)
Bearbeiten: Im Nachhinein scheint dies unnötige Zauberei zu sein. Ich würde stattdessen so etwas tun:
def find_last(lst, sought_elt): for r_idx, elt in enumerate(reversed(lst)): if elt == sought_elt: return len(lst) - 1 - r_idx
quelle
>>> (x for x in reversed([y for y in enumerate(li)]) if x[1] == 'a').next()[0] 6 >>> len(li) - (x for x in (y for y in enumerate(li[::-1])) if x[1] == 'a').next()[0] - 1 6
quelle
reversed(enumerate(li))
?reversed(enumerate(li))
führt dies zu einem Fehler, der lautetargument to reversed() must be a sequence
! Und das steht auch fürreversed((y for y in enumarete(li))
!reversed()
Iteratoren im Allgemeinen, einschließlich Generatoren, nicht ausgeführt werden können. Dasenumerate(reversed(li))
Anpassen der Indexkomponente der aufgezählten Tupel ist eine Problemumgehung, bei der keine Kopie der Liste erstellt wird.Ich mag sowohl Wims als auch Ignacios Antworten. Ich denke jedoch, dass es
itertools
trotz Lambda eine etwas besser lesbare Alternative gibt. (Für Python 3; für Python 2xrange
anstelle vonrange
).>>> from itertools import dropwhile >>> l = list('apples') >>> l.index('p') 1 >>> next(dropwhile(lambda x: l[x] != 'p', reversed(range(len(l))))) 2
Dies löst eine
StopIteration
Ausnahme aus, wenn das Element nicht gefunden wird. Sie könnten das fangen undValueError
stattdessen ein erhöhen , damit sich das genauso verhältindex
.Als Funktion definiert, um die
lambda
Verknüpfung zu vermeiden :def rindex(lst, item): def index_ne(x): return lst[x] != item try: return next(dropwhile(index_ne, reversed(range(len(lst))))) except StopIteration: raise ValueError("rindex(lst, item): item not in list")
Es funktioniert auch für Nicht-Zeichen. Geprüft:
>>> rindex(['apples', 'oranges', 'bananas', 'apples'], 'apples') 3
quelle
next
, so dass Sie dietry... except
if
Erklärung haben und eineValueError
darin erheben . (Denken Sie daran, dass wir versuchen, dieindex
API genau zu duplizieren , was bedeutet, dass ein ausgelöst wird,ValueError
wenn das Element nicht gefunden werden kann.) Die Verwendungtry
in diesem Kontext ist idiomatischer und, wie ich vermute, effizienter.IndexError
eher erhöhen alsValueError
, um im Einklang zu sein.index
?IndexError
dient zum Übergeben eines falschen Index. Wenn Sie einen fehlenden Wert übergeben,index
wird a generiertValueError
.Mit
dict
Sie können die Tatsache verwenden, dass Wörterbuchschlüssel eindeutig sind und beim Erstellen eines Schlüssels mit Tupeln nur die letzte Zuweisung eines Werts für einen bestimmten Schlüssel verwendet wird. Wie in anderen Antworten angegeben, ist dies für kleine Listen in Ordnung, erstellt jedoch ein Wörterbuch für alle eindeutigen Werte und ist für große Listen möglicherweise nicht effizient.
dict(map(reversed, enumerate(li)))["a"] 6
quelle
Ich kam hierher in der Hoffnung, jemanden zu finden, der bereits die effizienteste Version von geschrieben hatte
list.rindex
, die die vollständige Oberfläche vonlist.index
(einschließlich optionalstart
undstop
Parameter) bereitstellte . Das habe ich in den Antworten auf diese Frage nicht gefunden, oder hier oder hier oder hier . Also habe ich das selbst zusammengestellt ... indem ich Vorschläge aus anderen Antworten auf diese und die anderen Fragen verwendet habe.def rindex(seq, value, start=None, stop=None): """L.rindex(value, [start, [stop]]) -> integer -- return last index of value. Raises ValueError if the value is not present.""" start, stop, _ = slice(start, stop).indices(len(seq)) if stop == 0: # start = 0 raise ValueError('{!r} is not in list'.format(value)) else: stop -= 1 start = None if start == 0 else start - 1 return stop - seq[stop:start:-1].index(value)
Die
len(seq) - 1 - next(i for i,v in enumerate(reversed(seq)) if v == value)
in mehreren anderen Antworten vorgeschlagene Technik kann platzsparender sein: Es muss keine umgekehrte Kopie der vollständigen Liste erstellt werden. Aber in meinen (beiläufigen, gelegentlichen) Tests ist es ungefähr 50% langsamer.quelle
Verwenden Sie eine einfache Schleife:
def reversed_index(items, value): for pos, curr in enumerate(reversed(items)): if curr == value: return len(items) - pos - 1 raise ValueError("{0!r} is not in list".format(value))
quelle
last_occurence=len(yourlist)-yourlist[::-1].index(element)-1
So einfach ist das. Sie müssen keine Funktion importieren oder erstellen.
quelle
lastIndexOf = lambda array, item: len(array) - (array[::-1].index(item)) - 1
quelle
def rindex(lst, val): try: return next(len(lst)-i for i, e in enumerate(reversed(lst), start=1) if e == val) except StopIteration: raise ValueError('{} is not in list'.format(val))
quelle
val = [1,2,2,2,2,2,4,5].
Wenn Sie das letzte Vorkommen von 2 finden müssen
last_occurence = (len(val) -1) - list(reversed(val)).index(2)
quelle
Hier ist ein kleiner Einzeiler, um den letzten Index zu erhalten, zu verwenden
enumerate
und ein Listenverständnis zu erhalten:li = ["a", "b", "a", "c", "x", "d", "a", "6"] [l[0] for l in enumerate(li) if l[1] == "a"][-1]
quelle