4394 Stimmen

Wie finde ich den Index für ein bestimmtes Element in einer Liste?

Gegeben eine Liste ["foo", "bar", "baz"] und ein Element in der Liste "bar", wie erhalte ich seinen Index 1?

16 Stimmen

Übersetzung: Kehren Sie zurück: [1] Der niedrigste Index im Falle mehrerer Instanzen von "bar", [2] Alle Indizes von "bar"?

7 Stimmen

A) Ist es garantiert, dass der Eintrag in der Liste ist, oder wie sollten wir den Fehlerfall behandeln? (None zurückgeben/ ValueError werfen) b) Sind Listeneinträge garantiert einzigartig, und sollten wir den ersten Index eines Treffers zurückgeben oder alle Indizes?

1 Stimmen

Betrachten Sie die Antworten mit numpy-Integration, numpy-Arrays sind weitaus effizienter als Python-Listen. Wenn die Liste kurz ist, ist es kein Problem, eine Kopie davon aus einer Python-Liste zu machen. Wenn nicht, sollten Sie vielleicht erwägen, die Elemente gleich von Anfang an in einem numpy-Array zu speichern.

5989voto

Alex Coventry Punkte 64405
>>> ["foo", "bar", "baz"].index("bar")
1

Siehe die Dokumentation für die integrierte Methode .index() der Liste:

list.index(x[, start[, end]])

Gibt den index in der Liste des ersten Elements zurück, dessen Wert gleich x ist. Wirft einen ValueError falls kein solches Element vorhanden ist.

Die optionalen Argumente start und end werden wie in der Slices-Notation interpretiert und dienen dazu, die Suche auf eine bestimmte Teilfolge der Liste zu begrenzen. Der zurückgegebene Index wird relativ zum Anfang der vollständigen Sequenz berechnet und nicht relativ zum Startargument.

Vorsichtsmaßnahmen

Lineare Zeitkomplexität in der Listenlänge

Ein index-Aufruf überprüft jedes Element der Liste der Reihe nach, bis es eine Übereinstimmung findet. Wenn die Liste lang ist und keine Garantie besteht, dass der Wert nahe am Anfang liegt, kann dies den Code verlangsamen.

Dieses Problem kann nur vollständig vermieden werden, indem eine andere Datenstruktur verwendet wird. Wenn jedoch bekannt ist, dass das Element in einem bestimmten Teil der Liste enthalten ist, können die Parameter start und end verwendet werden, um die Suche einzuschränken.

Zum Beispiel:

>>> import timeit
>>> timeit.timeit('l.index(999_999)', setup='l = list(range(0, 1_000_000))', number=1000)
9.356267921015387
>>> timeit.timeit('l.index(999_999, 999_990, 1_000_000)', setup='l = list(range(0, 1_000_000))', number=1000)
0.0004404920036904514

Der zweite Aufruf ist um Größenordnungen schneller, da er nur durch 10 Elemente suchen muss und nicht durch alle 1 Million.

Nur der Index der ersten Übereinstimmung wird zurückgegeben

Ein Aufruf von index durchsucht die Liste der Reihe nach, bis es eine Übereinstimmung findet, und stoppt dort. Wenn es mehr als eine Wiederholung des Werts geben könnte und alle Indizes benötigt werden, kann index das Problem nicht lösen:

>>> [1, 1].index(1) # der Index `1` wird nicht gefunden.
0

Verwenden Sie stattdessen eine List Comprehension oder Generator-Ausdruck zur Suche, mit enumerate zur Ermittlung der Indizes:

>>> # Eine List Comprehension gibt direkt eine Liste von Indizes zurück:
>>> [i for i, e in enumerate([1, 2, 1]) if e == 1]
[0, 2]
>>> # Ein Generator-Ausdruck gibt uns ein iterierbares Objekt...
>>> g = (i for i, e in enumerate([1, 2, 1]) if e == 1)
>>> # das in einer `for`-Schleife verwendet werden kann oder manuell mit `next` durchlaufen werden kann:
>>> next(g)
0
>>> next(g)
2

Die Techniken der List Comprehension und des Generatorausdrucks funktionieren auch bei nur einer Übereinstimmung und sind allgemeiner anwendbar.

Wirft eine Ausnahme, wenn keine Übereinstimmung vorhanden ist

Wie oben in der Dokumentation erwähnt, wirft die Verwendung von .index eine Ausnahme, wenn der gesuchte Wert nicht in der Liste vorhanden ist:

>>> [1, 1].index(2)
Traceback (most recent call last):
  File "", line 1, in 
ValueError: 2 is not in list

Wenn dies ein Problem ist, überprüfen Sie zuerst explizit mit Verwendung von Element in myList, oder behandeln Sie die Ausnahme mit try/except entsprechend.

Die explizite Überprüfung ist einfach und lesbar, erfordert jedoch eine erneute Iteration der Liste. Siehe Was ist das EAFP-Prinzip in Python? für weitere Anleitungen zu dieser Entscheidung.

45 Stimmen

Index gibt das erste Element zurück, dessen Wert "bar" ist. Wenn "bar" zweimal in der Liste existiert, finden Sie niemals den Schlüssel für das zweite "bar". Siehe Dokumentation: docs.python.org/3/tutorial/datastructures.html

11 Stimmen

Wenn Sie nur nach einem Element suchen, habe ich festgestellt, dass index() bei Listen von ganzen Zahlen etwa 90 % schneller ist als die Listenabstraktion.

2 Stimmen

Welche Datenstruktur sollte verwendet werden, wenn die Liste sehr lang ist?

993voto

davidavr Punkte 13933

Eine Sache, die beim Erlernen von Python wirklich hilfreich ist, besteht darin, die interaktive Hilfefunktion zu verwenden:

>>> help(["foo", "bar", "baz"])
Hilfe zu Listenobjekten:

class list(object)
 ...

 |
 |  index(...)
 |      L.index(value, [start, [stop]]) -> integer -- gibt den ersten Index des Werts zurück
 |

Was Sie oft zur gesuchten Methode führen wird.

13 Stimmen

bpython ist eine schöne, benutzerfreundliche Möglichkeit, die Dokumentation interaktiv zu lesen.

21 Stimmen

@davidavr ja, aber dann hätten wir anderen, die es einfach nur googeln wollen anstatt sich durch die Hilfeseiten zu scrollen, nicht diesen schönen, zentralen, geordneten Satz von Optionen. :)

714voto

TerryA Punkte 55828

Die meisten Antworten erklären, wie man einen einzigen Index findet, aber ihre Methoden geben keine mehrfachen Indizes zurück, wenn das Element mehrmals in der Liste vorkommt. Verwenden Sie enumerate():

for i, j in enumerate(['foo', 'bar', 'baz']):
    if j == 'bar':
        print(i)

Die Funktion index() gibt nur das erste Vorkommen zurück, während enumerate() alle Vorkommen zurückgibt.

Als Listenverständnis:

[i for i, j in enumerate(['foo', 'bar', 'baz']) if j == 'bar']

Hier ist auch eine weitere kleine Lösung mit itertools.count() (was im Wesentlichen der gleiche Ansatz wie enumerate ist):

from itertools import izip as zip, count # izip für maximale Effizienz
[i for i, j in zip(count(), ['foo', 'bar', 'baz']) if j == 'bar']

Dies ist effizienter für größere Listen als die Verwendung von enumerate():

$ python -m timeit -s "from itertools import izip as zip, count" "[i for i, j in zip(count(), ['foo', 'bar', 'baz']*500) if j == 'bar']"
10000 Schleifen, bester von 3: 174 Mikrosekunden pro Schleife
$ python -m timeit "[i for i, j in enumerate(['foo', 'bar', 'baz']*500) if j == 'bar']"
10000 Schleifen, bester von 3: 196 Mikrosekunden pro Schleife

3 Stimmen

Enumeration funktioniert besser für mich als die indexbasierten Methoden, da ich die Indizes von Zeichenfolgen mithilfe von 'startswith' sammeln möchte und ich mehrere Vorkommen sammeln muss. Oder gibt es einen Weg, den Index mit "startswith" zu verwenden, den ich nicht herausfinden konnte?

9 Stimmen

In meinen Händen ist die Aufzählungsversion durchweg etwas schneller. Einige Implementierungsdetails können sich seit der obigen Messung geändert haben.

4 Stimmen

Dies wurde bereits seit '11 beantwortet: stackoverflow.com/questions/6294179/…

242voto

FMc Punkte 40706

Um alle Indexe zu erhalten:

indexes = [i for i, x in enumerate(xs) if x == 'foo']

7 Stimmen

Es gibt bereits eine weitere Frage dazu, hinzugefügt in '11: stackoverflow.com/questions/6294179/…

158voto

HongboZhu Punkte 4262

index() gibt den ersten Index des Wertes zurück!

| index(...)
| L.index(value, [start, [stop]]) -> integer -- gibt den ersten Index des Wertes zurück

def all_indices(value, qlist):
    indices = []
    idx = -1
    while True:
        try:
            idx = qlist.index(value, idx+1)
            indices.append(idx)
        except ValueError:
            break
    return indices

all_indices("foo", ["foo","bar","baz","foo"])

3 Stimmen

Und wenn es nicht auf der Liste steht?

1 Stimmen

Das Nicht-Vorhandensein des Elements wird einen ValueError auslösen.

1 Stimmen

Diese Antwort würde hier besser passen: stackoverflow.com/questions/6294179/…

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X