Kehren Sie zurück: [1] Der niedrigste Index für den Fall, dass es mehrere Instanzen von gibt "bar", [2] Alle Indizes von "bar"?
12gǻňạcểơửṩ
4
a) Ist garantiert, dass sich das Element in der Liste befindet, oder wie sollen wir mit dem Fehlerfall umgehen? (Keine zurückgeben / ValueError erhöhen) b) Sind Listeneinträge garantiert eindeutig und sollten wir den ersten Index einer Übereinstimmung oder alle Indizes zurückgeben?
smci
Zeigen Sie die Antworten mit Numpy-Integration an. 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 erstellen. Wenn dies nicht der Fall ist, sollten Sie möglicherweise zunächst die Elemente in einem numpy-Array speichern.
Beachten Sie, dass , während die ist vielleicht der sauberste Weg , um die Frage zu beantworten , wie gefragt , indexist eine eher schwache Komponente der listAPI, und ich kann das letzte Mal nicht erinnern , habe ich es in Wut. In den Kommentaren wurde ich darauf hingewiesen, dass diese Antwort vollständiger gemacht werden sollte, da sie stark referenziert wird. Einige Vorbehalte list.indexfolgen. Es lohnt sich wahrscheinlich, zunächst einen Blick auf die Dokumentation zu werfen:
list.index(x[, start[, end]])
Gibt einen auf Null basierenden Index in der Liste des ersten Elements zurück, dessen Wert gleich x ist . Löst a aus, ValueErrorwenn es keinen solchen Gegenstand gibt.
Die optionalen Argumente beginnen und end werden wie in der Slice-Notation interpretiert und dienen dazu, die Suche auf eine bestimmte Teilsequenz der Liste zu beschränken. Der zurückgegebene Index wird relativ zum Anfang der vollständigen Sequenz und nicht zum Startargument berechnet.
Lineare Zeitkomplexität in der Listenlänge
Ein indexAufruf überprüft jedes Element der Liste der Reihe nach, bis eine Übereinstimmung gefunden wird. Wenn Ihre Liste lang ist und Sie nicht genau wissen, wo in der Liste sie vorkommt, kann diese Suche zu einem Engpass werden. In diesem Fall sollten Sie eine andere Datenstruktur berücksichtigen. Beachten Sie, dass Sie indexeinen Hinweis geben können, wenn Sie ungefähr wissen, wo Sie die Übereinstimmung finden . Zum Beispiel ist in diesem Snippet l.index(999_999, 999_990, 1_000_000)ungefähr fünf Größenordnungen schneller als geradel.index(999_999) , weil der erstere nur 10 Einträge durchsuchen muss, während der letztere eine Million durchsucht:
Gibt nur den Index des zurück ersten Übereinstimmung zu seinem Argument zurück
Ein Aufruf, indexdie Liste der Reihe nach zu durchsuchen, bis eine Übereinstimmung gefunden wird, und dort anzuhalten.Wenn Sie erwarten, dass Indizes mit mehr Übereinstimmungen benötigt werden, sollten Sie ein Listenverständnis oder einen Generatorausdruck verwenden.
>>>[1,1].index(1)0>>>[i for i, e in enumerate([1,2,1])if e ==1][0,2]>>> g =(i for i, e in enumerate([1,2,1])if e ==1)>>> next(g)0>>> next(g)2
Die meisten Orte, an denen ich einmal benutzt hätte index ich jetzt ein Listenverständnis oder einen Generatorausdruck, weil sie verallgemeinerbarer sind. Wenn Sie also nach etwas indexgreifen möchten, werfen Sie einen Blick auf diese hervorragenden Python-Funktionen.
Wird ausgelöst, wenn das Element nicht in der Liste vorhanden ist
Ein Aufruf von indexführt zu einem, ValueErrorwenn der Artikel nicht vorhanden ist.
>>>[1,1].index(2)Traceback(most recent call last):File"<stdin>", line 1,in<module>ValueError:2isnotin list
Wenn das Element möglicherweise nicht in der Liste vorhanden ist, sollten Sie dies auch tun
Überprüfen Sie es zuerst mit item in my_list (sauberer, lesbarer Ansatz) oder
Schließen Sie den indexAnruf in einen try/exceptBlock ein , der abfängt ValueError(wahrscheinlich schneller, zumindest wenn die zu durchsuchende Liste lang ist und das Element normalerweise vorhanden ist.)
index gibt das erste Element zurück, dessen Wert "bar" ist. Wenn "Balken" zweimal in der Liste vorhanden ist, finden Sie nie den Schlüssel für den zweiten "Balken". Siehe Dokumentation: docs.python.org/3/tutorial/datastructures.html
mpoletto
2
Wenn Sie nur nach einem Element (dem ersten) suchen, habe ich festgestellt, dass index()es knapp 90% schneller ist als das Listenverständnis gegenüber Listen von Ganzzahlen.
Slybloty
Welche Datenstruktur sollte verwendet werden, wenn die Liste sehr lang ist?
izhang05
@izhang: Ein zusätzlicher Index, wie ein {element -> list_index} -Diktat, wenn die Elemente hashbar sind und die Position in der Liste von Bedeutung ist.
Alex Coventry
898
Eine Sache, die beim Erlernen von Python wirklich hilfreich ist, ist die Verwendung der interaktiven Hilfefunktion:
>>> help(["foo","bar","baz"])Help on list object:class list(object)...|| index(...)| L.index(value,[start,[stop]])-> integer --return first index of value
|
Dies führt Sie häufig zu der Methode, nach der Sie suchen.
bpython ist eine nette benutzerfreundliche Möglichkeit, die Dokumente auf interaktive Weise zu lesen.
Goetzc
@davidavr ja, aber dann hätte der Rest von uns, der es nur googeln möchte, anstatt durch die Hilfedokumente zu scrollen, nicht diese nette, zentrale, geordnete Auswahl an Optionen. :)
Honkaboy
556
In den meisten Antworten wird erläutert, wie ein einzelner Index gefunden wird. Die Methoden geben jedoch nicht mehrere Indizes zurück, wenn das Element mehrmals in der Liste enthalten ist. Verwendung enumerate():
for i, j in enumerate(['foo','bar','baz']):if j =='bar':print(i)
Die index()Funktion gibt nur das erste Vorkommen zurück, währendenumerate() alle Vorkommen zurückgegeben werden.
Als Listenverständnis:
[i for i, j in enumerate(['foo','bar','baz'])if j =='bar']
Hier ist auch eine andere kleine Lösung mit itertools.count()(die so ziemlich dem gleichen Ansatz wie die Aufzählung entspricht):
from itertools import izip as zip, count # izip for maximum efficiency[i for i, j in zip(count(),['foo','bar','baz'])if j =='bar']
Dies ist für größere Listen effizienter 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 loops, best of 3:174 usec per loop
$ python -m timeit "[i for i, j in enumerate(['foo', 'bar', 'baz']*500) if j == 'bar']"10000 loops, best of 3:196 usec per loop
Die Aufzählung funktioniert für mich besser als die indexbasierten Methoden, da ich die Indizes von Zeichenfolgen mit 'Startswith' erfassen möchte und mehrere Vorkommen erfassen muss. Oder gibt es eine Möglichkeit, den Index mit 'Startswith' zu verwenden, die ich konnte nicht herausfinden
Tupelo Thistlehead
3
In meinen Händen ist die Aufzählungsversion durchweg etwas schneller. Einige Implementierungsdetails haben sich möglicherweise geändert, seit die obige Messung veröffentlicht wurde.
Ein Problem tritt auf, wenn das Element nicht in der Liste enthalten ist. Diese Funktion behandelt das Problem:
# if element is found it returns index of element else returns Nonedef find_element_in_list(element, list_element):try:
index_element = list_element.index(element)return index_element
exceptValueError:returnNone
Dies könnte jedoch die Komplexität verdoppeln. Hat jemand nachgesehen?
stefanct
@stefanct Die zeitliche Komplexität ist immer noch linear, durchläuft die Liste jedoch zweimal.
Annäherung
@ApproachingDarknessFish Das habe ich natürlich gemeint. Selbst wenn es pedantisch die gleiche Reihenfolge der Komplexität ist, kann das zweimalige Iterieren in vielen Anwendungsfällen ein schwerwiegender Nachteil sein, daher habe ich es angesprochen. Und wir wissen immer noch nicht die Antwort ...
stefanct
44
Alle hier vorgeschlagenen Funktionen reproduzieren das inhärente Sprachverhalten, verdecken jedoch, was vor sich geht.
[i for i in range(len(mylist))if mylist[i]==myterm]# get the indices[each for each in mylist if each==myterm]# get the items
mylist.index(myterm)if myterm in mylist elseNone# get the first index and fail quietly
Warum eine Funktion mit Ausnahmebehandlung schreiben, wenn die Sprache die Methoden bereitstellt, um selbst das zu tun, was Sie wollen?
Die 3. Methode durchläuft die Liste zweimal, oder?
Eric Duminil
Betreff: "Alle hier vorgeschlagenen Funktionen" : Zum Zeitpunkt des Schreibens vielleicht, aber Sie sollten neuere Antworten überprüfen, um festzustellen, ob sie noch wahr sind.
Dies ist die beste, die ich gelesen habe. 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 erstellen. Wenn dies nicht der Fall ist, sollte der Entwickler möglicherweise zunächst in Betracht ziehen, die Elemente in einem Numpy-Array zu speichern.
Athanassios
35
Suchen des Index eines Elements anhand einer Liste, die es in Python enthält
Was ist für eine Liste ["foo", "bar", "baz"]und ein Element in der Liste "bar"der sauberste Weg, um den Index (1) in Python zu erhalten?
Natürlich gibt es die Indexmethode, die den Index des ersten Auftretens zurückgibt:
>>> l =["foo","bar","baz"]>>> l.index('bar')1
Bei dieser Methode gibt es einige Probleme:
Wenn der Wert nicht in der Liste enthalten ist, erhalten Sie eine ValueError
Wenn mehr als einer der Werte in der Liste enthalten ist, erhalten Sie nur den Index für den ersten
Keine Werte
Wenn der Wert fehlen könnte, müssen Sie den abfangen ValueError.
Sie können dies mit einer wiederverwendbaren Definition wie der folgenden tun:
Und der Nachteil davon ist, dass Sie wahrscheinlich prüfen müssen, ob der zurückgegebene Wert isoder is notKeine:
result = index(a_list, value)if result isnotNone:
do_something(result)
Mehr als ein Wert in der Liste
Wenn Sie mehr Vorkommen haben könnten, erhalten Sie keine vollständigen Informationen mit list.index:
>>> l.append('bar')>>> l
['foo','bar','baz','bar']>>> l.index('bar')# nothing at index 3?1
Sie können die Indizes in ein Listenverständnis auflisten:
>>>[index for index, v in enumerate(l)if v =='bar'][1,3]>>>[index for index, v in enumerate(l)if v =='boink'][]
Wenn Sie keine Vorkommen haben, können Sie dies mit einer booleschen Überprüfung des Ergebnisses überprüfen oder einfach nichts tun, wenn Sie die Ergebnisse durchlaufen:
indexes =[index for index, v in enumerate(l)if v =='boink']for index in indexes:
do_something(index)
Besseres Datenmunging mit Pandas
Wenn Sie Pandas haben, können Sie diese Informationen einfach mit einem Serienobjekt abrufen:
>>>import pandas as pd
>>> series = pd.Series(l)>>> series
0 foo
1 bar
2 baz
3 bar
dtype: object
Eine Vergleichsprüfung gibt eine Reihe von Booleschen Werten zurück:
>>> series =='bar'0False1True2False3True
dtype: bool
Übergeben Sie diese Reihe von Booleschen Werten über die tiefgestellte Notation an die Reihe, und Sie erhalten nur die passenden Mitglieder:
>>> series[series =='bar']1 bar
3 bar
dtype: object
Wenn Sie nur die Indizes möchten, gibt das Indexattribut eine Reihe von Ganzzahlen zurück:
Und wenn Sie sie in einer Liste oder einem Tupel haben möchten, übergeben Sie sie einfach an den Konstruktor:
>>> list(series[series =='bar'].index)[1,3]
Ja, Sie könnten auch ein Listenverständnis mit Aufzählung verwenden, aber das ist meiner Meinung nach nicht so elegant - Sie führen in Python Tests auf Gleichheit durch, anstatt den in C geschriebenen eingebauten Code damit umgehen zu lassen:
>>>[i for i, value in enumerate(l)if value =='bar'][1,3]
Das XY-Problem fragt eher nach Ihrem Lösungsversuch als nach Ihrem eigentlichen Problem.
Warum muss der Index Ihrer Meinung nach ein Element in einer Liste enthalten?
Wenn Sie den Wert bereits kennen, warum interessiert es Sie, wo er in einer Liste steht?
Wenn der Wert nicht vorhanden ist, ist das Fangen des Werts ValueErrorziemlich ausführlich - und das vermeide ich lieber.
Normalerweise iteriere ich sowieso über die Liste, daher behalte ich normalerweise einen Zeiger auf interessante Informationen und erhalte den Index mit Aufzählung.
Wenn Sie Daten mungieren, sollten Sie wahrscheinlich Pandas verwenden - die weitaus elegantere Tools haben als die reinen Python-Problemumgehungen, die ich gezeigt habe.
Ich erinnere list.indexmich nicht daran , mich selbst gebraucht zu haben. Ich habe jedoch die Python-Standardbibliothek durchgesehen und sehe einige hervorragende Verwendungsmöglichkeiten dafür.
Es gibt viele, viele Verwendungsmöglichkeiten idlelibfür GUI und Textanalyse.
Das keywordModul verwendet es, um Kommentarmarkierungen im Modul zu finden, um die Liste der darin enthaltenen Schlüsselwörter über die Metaprogrammierung automatisch neu zu generieren.
In Lib / mailbox.py scheint es wie eine geordnete Zuordnung verwendet zu werden:
key_list[key_list.index(old)]= new
und
del key_list[key_list.index(key)]
In Lib / http / cookiejar.py scheint verwendet zu werden, um den nächsten Monat zu bekommen:
mon = MONTHS_LOWER.index(mon.lower())+1
In Lib / tarfile.py ähnlich wie bei distutils, um ein Stück auf einen Gegenstand zu bringen:
members = members[:members.index(tarinfo)]
In Lib / pickletools.py:
numtopop = before.index(markobject)
Was diese Verwendungen gemeinsam zu haben scheinen, ist, dass sie auf Listen mit eingeschränkten Größen zu arbeiten scheinen (wichtig wegen der O (n) -Suchzeit für list.index ) und hauptsächlich beim Parsen verwendet werden (und bei der Benutzeroberfläche im Leerlauf).
Es gibt zwar Anwendungsfälle dafür, diese sind jedoch eher ungewöhnlich. Wenn Sie nach dieser Antwort suchen, fragen Sie sich, ob Sie die Tools, die von der Sprache für Ihren Anwendungsfall bereitgestellt werden, am direktesten verwenden.
Abrufen aller Vorkommen und der Position eines oder mehrerer (identischer) Elemente in einer Liste
Mit enumerate (alist) können Sie das erste Element (n) speichern, das der Index der Liste ist, wenn das Element x dem entspricht, wonach Sie suchen.
>>> alist =['foo','spam','egg','foo']>>> foo_indexes =[n for n,x in enumerate(alist)if x=='foo']>>> foo_indexes
[0,3]>>>
Lassen Sie uns unsere Funktion findindex machen
Diese Funktion verwendet das Element und die Liste als Argumente und gibt die Position des Elements in der Liste zurück, wie wir zuvor gesehen haben.
def indexlist(item2find, list_or_string):"Returns all indexes of an item in a list or a string"return[n for n,item in enumerate(list_or_string)if item==item2find]print(indexlist("1","010101010"))
Ausgabe
[1,3,5,7]
Einfach
for n, i in enumerate([1,2,3,4,1]):if i ==1:print(n)
>>> a =['red','blue','green','red']>>> b ='red'>>> offset =0;>>> indices = list()>>>for i in range(a.count(b)):... indices.append(a.index(b,offset))... offset = indices[-1]+1...>>> indices
[0,3]>>>
... wie die Existenz des Elements zu bestätigen, bevor der Index abgerufen wird. Das Schöne an diesem Ansatz ist, dass die Funktion immer eine Liste von Indizes zurückgibt - auch wenn es sich um eine leere Liste handelt. Es funktioniert auch mit Strings.
def indices(l, val):"""Always returns a list containing the indices of val in the_list"""
retval =[]
last =0while val in l[last:]:
i = l[last:].index(val)
retval.append(last + i)
last += i +1return retval
l =['bar','foo','bar','baz','bar','bar']
q ='bar'print indices(l,q)print indices(l,'bat')print indices('abcdaababb','a')
Beim Einfügen in ein interaktives Python-Fenster:
Python2.7.6(v2.7.6:3a1db0d2747e,Nov102013,00:42:54)[GCC 4.2.1(AppleInc. build 5666)(dot 3)] on darwin
Type"help","copyright","credits"or"license"for more information.>>>def indices(the_list, val):..."""Always returns a list containing the indices of val in the_list"""... retval =[]... last =0...while val in the_list[last:]:... i = the_list[last:].index(val)... retval.append(last + i)... last += i +1...return retval
...>>> l =['bar','foo','bar','baz','bar','bar']>>> q ='bar'>>>print indices(l,q)[0,2,4,5]>>>print indices(l,'bat')[]>>>print indices('abcdaababb','a')[0,4,5,7]>>>
Aktualisieren
Nach einem weiteren Jahr der Heads-Down-Python-Entwicklung ist mir meine ursprüngliche Antwort etwas peinlich. Um den Rekord zu korrigieren, kann man sicherlich den obigen Code verwenden. die viel idiomatischere Weg, um dasselbe Verhalten zu erzielen, wäre jedoch, das Listenverständnis zusammen mit der Funktion enumerate () zu verwenden.
Etwas wie das:
def indices(l, val):"""Always returns a list containing the indices of val in the_list"""return[index for index, value in enumerate(l)if value == val]
l =['bar','foo','bar','baz','bar','bar']
q ='bar'print indices(l,q)print indices(l,'bat')print indices('abcdaababb','a')
Was beim Einfügen in ein interaktives Python-Fenster Folgendes ergibt:
Python2.7.14|Anaconda,Inc.|(default,Dec72017,11:07:58)[GCC 4.2.1CompatibleClang4.0.1(tags/RELEASE_401/final)] on darwin
Type"help","copyright","credits"or"license"for more information.>>>def indices(l, val):..."""Always returns a list containing the indices of val in the_list"""...return[index for index, value in enumerate(l)if value == val]...>>> l =['bar','foo','bar','baz','bar','bar']>>> q ='bar'>>>print indices(l,q)[0,2,4,5]>>>print indices(l,'bat')[]>>>print indices('abcdaababb','a')[0,4,5,7]>>>
Und jetzt, nachdem ich diese Frage und alle Antworten überprüft habe, stelle ich fest, dass dies genau das ist, was FMc in seiner früheren Antwort vorgeschlagen hat . Zu der Zeit, als ich diese Frage ursprünglich beantwortete, tat ich es nicht einmal sehen , dass die Antwort, weil ich es nicht verstand. Ich hoffe, dass mein etwas ausführlicheres Beispiel das Verständnis erleichtert.
Wenn die obige einzelne Codezeile für Sie immer noch keinen Sinn ergibt , empfehle ich Ihnen dringend, Google 'Python-Listenverständnis' zu verwenden, und nehmen Sie sich ein paar Minuten Zeit, um sich mit Ihnen vertraut zu machen. Es ist nur eine der vielen leistungsstarken Funktionen, die es zum Vergnügen machen, mit Python Code zu entwickeln.
Eine Variante der Antwort von FMc und user7177 gibt ein Diktat aus, das alle Indizes für jeden Eintrag zurückgeben kann:
>>> a =['foo','bar','baz','bar','any','foo','much']>>> l = dict(zip(set(a), map(lambda y:[i for i,z in enumerate(a)if z is y ], set(a))))>>> l['foo'][0,5]>>> l ['much'][6]>>> l
{'baz':[2],'foo':[0,5],'bar':[1,3],'any':[4],'much':[6]}>>>
Sie können dies auch als Einzeiler verwenden, um alle Indizes für einen einzelnen Eintrag abzurufen. Es gibt keine Garantien für die Effizienz, obwohl ich Satz (a) verwendet habe, um die Häufigkeit zu verringern, mit der das Lambda aufgerufen wird.
Diese Lösung ist nicht so leistungsfähig wie andere, aber wenn Sie ein Anfänger sind und nur über forSchleifen Bescheid wissen, ist es immer noch möglich, den ersten Index eines Elements zu finden, während Sie den ValueError vermeiden:
def find_element(p,t):
i =0for e in p:if e == t:return i
else:
i +=1return-1
Dadurch wird das Array zweimal wiederholt, sodass bei großen Arrays Leistungsprobleme auftreten können.
Cristik
Zustimmen. Wenn die Listen sehr lang sind, würde ich mich für etwas anderes entscheiden. Sollte für kleine bis mittlere Listen jedoch keine große Sache sein.
Ketan
5
Da Python-Listen auf Null basieren, können wir die integrierte Zip-Funktion wie folgt verwenden:
>>>[i for i,j in zip(range(len(haystack)), haystack)if j =='needle']
Dabei ist "Heuhaufen" die betreffende Liste und "Nadel" das zu suchende Element.
(Hinweis: Hier iterieren wir mit i, um die Indizes zu erhalten. Wenn wir uns jedoch eher auf die Elemente konzentrieren müssen, können wir zu j wechseln.)
[i für i, j in Aufzählung (Heuhaufen), wenn j == 'Nadel'] kompakter und lesbarer ist, denke ich.
Giovanni G. PY
5
name ="bar"
list =[["foo",1],["bar",2],["baz",3]]
new_list=[]for item in list:
new_list.append(item[0])print(new_list)try:
location= new_list.index(name)except:
location=-1print(location)
Dies erklärt, wenn die Zeichenfolge nicht auch in der Liste enthalten ist, wenn sie dann nicht in der Liste enthalten ist location = -1
Die Python- index()Methode gibt einen Fehler aus, wenn das Element nicht gefunden wurde. Stattdessen können Sie es der indexOf()Funktion von JavaScript ähnlich machen, die zurückgibt, -1wenn das Element nicht gefunden wurde:
try:
index = array.index('search_keyword')exceptValueError:
index =-1
jedoch JavaScript hat die Philosophie , dass seltsame Ergebnisse sind besser als Fehler, so macht es Sinn zu geben -1 zurück, aber in Python, kann es schwer aufzuspüren Fehler machen, da -1 kehrt ein Element aus dem Ende der Liste.
Diese Antwort fühlt sich für Scala/ funktionale Programmier- Enthusiasten zu Hause
y2k-shubham
3
Geben wir lstder Liste, die Sie haben , den Namen . Man kann die Liste lstin eine konvertieren numpy array. Verwenden Sie dann numpy.where , um den Index des ausgewählten Elements in der Liste abzurufen . Im Folgenden wird beschrieben, wie Sie es implementieren.
import numpy as np
lst =["foo","bar","baz"]#lst: : 'list' data typeprint np.where( np.array(lst)=='bar')[0][0]>>>1
Für diejenigen, die aus einer anderen Sprache wie mir kommen, ist es vielleicht mit einer einfachen Schleife einfacher, sie zu verstehen und zu verwenden:
Wenn Sie einmal einen Index finden, ist die Verwendung der "Index" -Methode in Ordnung. Wenn Sie Ihre Daten jedoch mehrmals durchsuchen möchten, empfehle ich die Verwendung des Halbierungsmoduls . Beachten Sie, dass die Daten des Halbierungsmoduls sortiert werden müssen. Sie sortieren die Daten also einmal und können dann die Halbierung verwenden. Die Verwendung des Halbierungsmoduls auf meinem Computer ist etwa 20-mal schneller als die Verwendung der Indexmethode.
Hier ist ein Beispiel für Code mit Python 3.8 und höher:
import bisect
from timeit import timeit
def bisect_search(container, value):return(
index
if(index := bisect.bisect_left(container, value))< len(container)and container[index]== value else-1)
data = list(range(1000))# value to search
value =666# times to test
ttt =1000
t1 = timeit(lambda: data.index(value), number=ttt)
t2 = timeit(lambda: bisect_search(data, value), number=ttt)print(f"{t1=:.4f}, {t2=:.4f}, diffs {t1/t2=:.2f}")
In zahlreichen Antworten wird erwähnt, dass die eingebaute list.index(item)Methode ein O (n) -Algorithmus ist. Es ist in Ordnung, wenn Sie dies einmal ausführen müssen. Wenn Sie jedoch mehrmals auf die Indizes von Elementen zugreifen müssen, ist es sinnvoller, zuerst ein Wörterbuch (O (n)) von Element-Index-Paaren zu erstellen und dann bei Bedarf auf den Index bei O (1) zuzugreifen es.
Wenn Sie sicher sind, dass die Elemente in Ihrer Liste niemals wiederholt werden, können Sie ganz einfach:
myList =["foo","bar","baz"]# Create the dictionary
myDict = dict((e,i)for i,e in enumerate(myList))# Lookup
myDict["bar"]# Returns 1# myDict.get("blah") if you don't want an error to be raised if element not found.
Wenn Sie möglicherweise doppelte Elemente haben und alle ihre Indizes zurückgeben müssen:
from collections import defaultdict as dd
myList =["foo","bar","bar","baz","foo"]# Create the dictionary
myDict = dd(list)for i,e in enumerate(myList):
myDict[e].append(i)# Lookup
myDict["foo"]# Returns [0, 4]
Meiner Meinung nach ["foo", "bar", "baz"].index("bar")ist das gut, aber es ist nicht genug! Denn wenn "bar" nicht im Wörterbuch ist, wird es ValueErrorausgelöst. Also können Sie diese Funktion verwenden:
Verwenden Sie dies nicht, da l = [1, 2]; find_index(l, 3)es zurückkehren -1und zurückkehren l[find_index(l, 3)]würde 2. -1 ist eine schlechte Sache, um zurückzukehren, geben Sie einfach None zurück.
Daniel Stracaboško
-1 ist ein Vertrag, den Sie zurückgeben können, was immer Sie wollen. Versuchen Sie jedoch, in Ihren Programmen weniger None zu verwenden, da None oder Null bei der Kommunikation Ihres Programms mit anderen Programmen wie Android- und PHP-Websites zu Programmunterbrechungen führen kann. Beispielsweise können Sie in JSON null zurückgeben und Ihre Website-Telefonanwendung wird geschlossen oder gibt Fehler 500 zurück (interner Serverfehler).
"bar"
, [2] Alle Indizes von"bar"
?Antworten:
Referenz: Datenstrukturen> Mehr zu Listen
Vorsichtsmaßnahmen folgen
Beachten Sie, dass , während die ist vielleicht der sauberste Weg , um die Frage zu beantworten , wie gefragt ,
index
ist eine eher schwache Komponente derlist
API, und ich kann das letzte Mal nicht erinnern , habe ich es in Wut. In den Kommentaren wurde ich darauf hingewiesen, dass diese Antwort vollständiger gemacht werden sollte, da sie stark referenziert wird. Einige Vorbehaltelist.index
folgen. Es lohnt sich wahrscheinlich, zunächst einen Blick auf die Dokumentation zu werfen:Lineare Zeitkomplexität in der Listenlänge
Ein
index
Aufruf überprüft jedes Element der Liste der Reihe nach, bis eine Übereinstimmung gefunden wird. Wenn Ihre Liste lang ist und Sie nicht genau wissen, wo in der Liste sie vorkommt, kann diese Suche zu einem Engpass werden. In diesem Fall sollten Sie eine andere Datenstruktur berücksichtigen. Beachten Sie, dass Sieindex
einen Hinweis geben können, wenn Sie ungefähr wissen, wo Sie die Übereinstimmung finden . Zum Beispiel ist in diesem Snippetl.index(999_999, 999_990, 1_000_000)
ungefähr fünf Größenordnungen schneller als geradel.index(999_999)
, weil der erstere nur 10 Einträge durchsuchen muss, während der letztere eine Million durchsucht:Gibt nur den Index des zurück ersten Übereinstimmung zu seinem Argument zurück
Ein Aufruf,
index
die Liste der Reihe nach zu durchsuchen, bis eine Übereinstimmung gefunden wird, und dort anzuhalten.Wenn Sie erwarten, dass Indizes mit mehr Übereinstimmungen benötigt werden, sollten Sie ein Listenverständnis oder einen Generatorausdruck verwenden.Die meisten Orte, an denen ich einmal benutzt hätte
index
ich jetzt ein Listenverständnis oder einen Generatorausdruck, weil sie verallgemeinerbarer sind. Wenn Sie also nach etwasindex
greifen möchten, werfen Sie einen Blick auf diese hervorragenden Python-Funktionen.Wird ausgelöst, wenn das Element nicht in der Liste vorhanden ist
Ein Aufruf von
index
führt zu einem,ValueError
wenn der Artikel nicht vorhanden ist.Wenn das Element möglicherweise nicht in der Liste vorhanden ist, sollten Sie dies auch tun
item in my_list
(sauberer, lesbarer Ansatz) oderindex
Anruf in einentry/except
Block ein , der abfängtValueError
(wahrscheinlich schneller, zumindest wenn die zu durchsuchende Liste lang ist und das Element normalerweise vorhanden ist.)quelle
index()
es knapp 90% schneller ist als das Listenverständnis gegenüber Listen von Ganzzahlen.Eine Sache, die beim Erlernen von Python wirklich hilfreich ist, ist die Verwendung der interaktiven Hilfefunktion:
Dies führt Sie häufig zu der Methode, nach der Sie suchen.
quelle
In den meisten Antworten wird erläutert, wie ein einzelner Index gefunden wird. Die Methoden geben jedoch nicht mehrere Indizes zurück, wenn das Element mehrmals in der Liste enthalten ist. Verwendung
enumerate()
:Die
index()
Funktion gibt nur das erste Vorkommen zurück, währendenumerate()
alle Vorkommen zurückgegeben werden.Als Listenverständnis:
Hier ist auch eine andere kleine Lösung mit
itertools.count()
(die so ziemlich dem gleichen Ansatz wie die Aufzählung entspricht):Dies ist für größere Listen effizienter als die Verwendung von
enumerate()
:quelle
So erhalten Sie alle Indizes:
quelle
index()
gibt den ersten Wertindex zurück!quelle
Ein Problem tritt auf, wenn das Element nicht in der Liste enthalten ist. Diese Funktion behandelt das Problem:
quelle
quelle
Sie müssen eine Bedingung festlegen, um zu überprüfen, ob das gesuchte Element in der Liste enthalten ist
quelle
Alle hier vorgeschlagenen Funktionen reproduzieren das inhärente Sprachverhalten, verdecken jedoch, was vor sich geht.
Warum eine Funktion mit Ausnahmebehandlung schreiben, wenn die Sprache die Methoden bereitstellt, um selbst das zu tun, was Sie wollen?
quelle
Wenn Sie alle Indizes möchten, können Sie NumPy verwenden :
Es ist eine klare, lesbare Lösung.
quelle
Natürlich gibt es die Indexmethode, die den Index des ersten Auftretens zurückgibt:
Bei dieser Methode gibt es einige Probleme:
ValueError
Keine Werte
Wenn der Wert fehlen könnte, müssen Sie den abfangen
ValueError
.Sie können dies mit einer wiederverwendbaren Definition wie der folgenden tun:
Und benutze es so:
Und der Nachteil davon ist, dass Sie wahrscheinlich prüfen müssen, ob der zurückgegebene Wert
is
oderis not
Keine:Mehr als ein Wert in der Liste
Wenn Sie mehr Vorkommen haben könnten, erhalten Sie keine vollständigen Informationen mit
list.index
:Sie können die Indizes in ein Listenverständnis auflisten:
Wenn Sie keine Vorkommen haben, können Sie dies mit einer booleschen Überprüfung des Ergebnisses überprüfen oder einfach nichts tun, wenn Sie die Ergebnisse durchlaufen:
Besseres Datenmunging mit Pandas
Wenn Sie Pandas haben, können Sie diese Informationen einfach mit einem Serienobjekt abrufen:
Eine Vergleichsprüfung gibt eine Reihe von Booleschen Werten zurück:
Übergeben Sie diese Reihe von Booleschen Werten über die tiefgestellte Notation an die Reihe, und Sie erhalten nur die passenden Mitglieder:
Wenn Sie nur die Indizes möchten, gibt das Indexattribut eine Reihe von Ganzzahlen zurück:
Und wenn Sie sie in einer Liste oder einem Tupel haben möchten, übergeben Sie sie einfach an den Konstruktor:
Ja, Sie könnten auch ein Listenverständnis mit Aufzählung verwenden, aber das ist meiner Meinung nach nicht so elegant - Sie führen in Python Tests auf Gleichheit durch, anstatt den in C geschriebenen eingebauten Code damit umgehen zu lassen:
Ist das ein XY-Problem ?
Warum muss der Index Ihrer Meinung nach ein Element in einer Liste enthalten?
Wenn Sie den Wert bereits kennen, warum interessiert es Sie, wo er in einer Liste steht?
Wenn der Wert nicht vorhanden ist, ist das Fangen des Werts
ValueError
ziemlich ausführlich - und das vermeide ich lieber.Normalerweise iteriere ich sowieso über die Liste, daher behalte ich normalerweise einen Zeiger auf interessante Informationen und erhalte den Index mit Aufzählung.
Wenn Sie Daten mungieren, sollten Sie wahrscheinlich Pandas verwenden - die weitaus elegantere Tools haben als die reinen Python-Problemumgehungen, die ich gezeigt habe.
Ich erinnere
list.index
mich nicht daran , mich selbst gebraucht zu haben. Ich habe jedoch die Python-Standardbibliothek durchgesehen und sehe einige hervorragende Verwendungsmöglichkeiten dafür.Es gibt viele, viele Verwendungsmöglichkeiten
idlelib
für GUI und Textanalyse.Das
keyword
Modul verwendet es, um Kommentarmarkierungen im Modul zu finden, um die Liste der darin enthaltenen Schlüsselwörter über die Metaprogrammierung automatisch neu zu generieren.In Lib / mailbox.py scheint es wie eine geordnete Zuordnung verwendet zu werden:
und
In Lib / http / cookiejar.py scheint verwendet zu werden, um den nächsten Monat zu bekommen:
In Lib / tarfile.py ähnlich wie bei distutils, um ein Stück auf einen Gegenstand zu bringen:
In Lib / pickletools.py:
Was diese Verwendungen gemeinsam zu haben scheinen, ist, dass sie auf Listen mit eingeschränkten Größen zu arbeiten scheinen (wichtig wegen der O (n) -Suchzeit für
list.index
) und hauptsächlich beim Parsen verwendet werden (und bei der Benutzeroberfläche im Leerlauf).Es gibt zwar Anwendungsfälle dafür, diese sind jedoch eher ungewöhnlich. Wenn Sie nach dieser Antwort suchen, fragen Sie sich, ob Sie die Tools, die von der Sprache für Ihren Anwendungsfall bereitgestellt werden, am direktesten verwenden.
quelle
Alle Indizes mit der
zip
Funktion:quelle
Abrufen aller Vorkommen und der Position eines oder mehrerer (identischer) Elemente in einer Liste
Mit enumerate (alist) können Sie das erste Element (n) speichern, das der Index der Liste ist, wenn das Element x dem entspricht, wonach Sie suchen.
Lassen Sie uns unsere Funktion findindex machen
Diese Funktion verwendet das Element und die Liste als Argumente und gibt die Position des Elements in der Liste zurück, wie wir zuvor gesehen haben.
Ausgabe
Einfach
Ausgabe:
quelle
Einfach kann man mitgehen
quelle
Andere Option
quelle
Und jetzt etwas ganz anderes...
... wie die Existenz des Elements zu bestätigen, bevor der Index abgerufen wird. Das Schöne an diesem Ansatz ist, dass die Funktion immer eine Liste von Indizes zurückgibt - auch wenn es sich um eine leere Liste handelt. Es funktioniert auch mit Strings.
Beim Einfügen in ein interaktives Python-Fenster:
Aktualisieren
Nach einem weiteren Jahr der Heads-Down-Python-Entwicklung ist mir meine ursprüngliche Antwort etwas peinlich. Um den Rekord zu korrigieren, kann man sicherlich den obigen Code verwenden. die viel idiomatischere Weg, um dasselbe Verhalten zu erzielen, wäre jedoch, das Listenverständnis zusammen mit der Funktion enumerate () zu verwenden.
Etwas wie das:
Was beim Einfügen in ein interaktives Python-Fenster Folgendes ergibt:
Und jetzt, nachdem ich diese Frage und alle Antworten überprüft habe, stelle ich fest, dass dies genau das ist, was FMc in seiner früheren Antwort vorgeschlagen hat . Zu der Zeit, als ich diese Frage ursprünglich beantwortete, tat ich es nicht einmal sehen , dass die Antwort, weil ich es nicht verstand. Ich hoffe, dass mein etwas ausführlicheres Beispiel das Verständnis erleichtert.
Wenn die obige einzelne Codezeile für Sie immer noch keinen Sinn ergibt , empfehle ich Ihnen dringend, Google 'Python-Listenverständnis' zu verwenden, und nehmen Sie sich ein paar Minuten Zeit, um sich mit Ihnen vertraut zu machen. Es ist nur eine der vielen leistungsstarken Funktionen, die es zum Vergnügen machen, mit Python Code zu entwickeln.
quelle
Eine Variante der Antwort von FMc und user7177 gibt ein Diktat aus, das alle Indizes für jeden Eintrag zurückgeben kann:
Sie können dies auch als Einzeiler verwenden, um alle Indizes für einen einzelnen Eintrag abzurufen. Es gibt keine Garantien für die Effizienz, obwohl ich Satz (a) verwendet habe, um die Häufigkeit zu verringern, mit der das Lambda aufgerufen wird.
quelle
Diese Lösung ist nicht so leistungsfähig wie andere, aber wenn Sie ein Anfänger sind und nur über
for
Schleifen Bescheid wissen, ist es immer noch möglich, den ersten Index eines Elements zu finden, während Sie den ValueError vermeiden:quelle
Index von Element x in Liste L finden:
quelle
Da Python-Listen auf Null basieren, können wir die integrierte Zip-Funktion wie folgt verwenden:
Dabei ist "Heuhaufen" die betreffende Liste und "Nadel" das zu suchende Element.
(Hinweis: Hier iterieren wir mit i, um die Indizes zu erhalten. Wenn wir uns jedoch eher auf die Elemente konzentrieren müssen, können wir zu j wechseln.)
quelle
Dies erklärt, wenn die Zeichenfolge nicht auch in der Liste enthalten ist, wenn sie dann nicht in der Liste enthalten ist
location = -1
quelle
Die Python-
index()
Methode gibt einen Fehler aus, wenn das Element nicht gefunden wurde. Stattdessen können Sie es derindexOf()
Funktion von JavaScript ähnlich machen, die zurückgibt,-1
wenn das Element nicht gefunden wurde:quelle
Darauf gibt es eine funktionalere Antwort.
Allgemeinere Form:
quelle
Scala
/ funktionale Programmier- Enthusiasten zu HauseGeben wir
lst
der Liste, die Sie haben , den Namen . Man kann die Listelst
in eine konvertierennumpy array
. Verwenden Sie dann numpy.where , um den Index des ausgewählten Elements in der Liste abzurufen . Im Folgenden wird beschrieben, wie Sie es implementieren.quelle
Für diejenigen, die aus einer anderen Sprache wie mir kommen, ist es vielleicht mit einer einfachen Schleife einfacher, sie zu verstehen und zu verwenden:
Ich bin dankbar für Also, was genau macht die Aufzählung? . Das hat mir geholfen zu verstehen.
quelle
Wenn Sie einmal einen Index finden, ist die Verwendung der "Index" -Methode in Ordnung. Wenn Sie Ihre Daten jedoch mehrmals durchsuchen möchten, empfehle ich die Verwendung des Halbierungsmoduls . Beachten Sie, dass die Daten des Halbierungsmoduls sortiert werden müssen. Sie sortieren die Daten also einmal und können dann die Halbierung verwenden. Die Verwendung des Halbierungsmoduls auf meinem Computer ist etwa 20-mal schneller als die Verwendung der Indexmethode.
Hier ist ein Beispiel für Code mit Python 3.8 und höher:
Ausgabe:
quelle
Wenn die Leistung von Belang ist:
In zahlreichen Antworten wird erwähnt, dass die eingebaute
list.index(item)
Methode ein O (n) -Algorithmus ist. Es ist in Ordnung, wenn Sie dies einmal ausführen müssen. Wenn Sie jedoch mehrmals auf die Indizes von Elementen zugreifen müssen, ist es sinnvoller, zuerst ein Wörterbuch (O (n)) von Element-Index-Paaren zu erstellen und dann bei Bedarf auf den Index bei O (1) zuzugreifen es.Wenn Sie sicher sind, dass die Elemente in Ihrer Liste niemals wiederholt werden, können Sie ganz einfach:
Wenn Sie möglicherweise doppelte Elemente haben und alle ihre Indizes zurückgeben müssen:
quelle
Wie von @TerryA angegeben, wird in vielen Antworten erläutert, wie ein Index gefunden wird.
more_itertools
ist eine Bibliothek eines Drittanbieters mit Tools zum Auffinden mehrerer Indizes innerhalb einer Iterable.Gegeben
Code
Finden Sie Indizes für mehrere Beobachtungen:
Testen Sie mehrere Elemente:
Siehe auch weitere Optionen mit
more_itertools.locate
. Installieren über> pip install more_itertools
.quelle
Verwenden Sie das Wörterbuch, wobei Sie zuerst die Liste verarbeiten und dann den Index hinzufügen
quelle
Meiner Meinung nach
["foo", "bar", "baz"].index("bar")
ist das gut, aber es ist nicht genug! Denn wenn "bar" nicht im Wörterbuch ist, wird esValueError
ausgelöst. Also können Sie diese Funktion verwenden:und das Ergebnis ist:
und wenn name nicht bei arr war, gibt die Funktion -1 zurück. Zum Beispiel:
quelle
l = [1, 2]; find_index(l, 3)
es zurückkehren-1
und zurückkehrenl[find_index(l, 3)]
würde2
. -1 ist eine schlechte Sache, um zurückzukehren, geben Sie einfach None zurück.