Czy zwracasz: [1] Najniższy indeks w przypadku wielu wystąpień "bar", [2] Wszystkie indeksy "bar"?
Ṃųỻịgǻňạcểơửṩ
4
a) Czy jest gwarantowane, że pozycja znajduje się na liście, czy też jak powinniśmy obsłużyć przypadek błędu? (return None / raise ValueError) b) Czy wpisy listy są gwarantowane jako unikalne i czy powinniśmy zwrócić pierwszy indeks dopasowania, czy wszystkie indeksy?
smci
Zobacz odpowiedzi z integracją numpy, tablice numpy są znacznie wydajniejsze niż listy Python. Jeśli lista jest krótka, nie ma problemu z utworzeniem jej kopii z listy Pythona, jeśli tak nie jest, być może powinieneś rozważyć przechowywanie elementów w tablicy numpy.
Zauważ, że chociaż jest to być może najczystszy sposób na udzielenie odpowiedzi na zadane pytanie , indexjest raczej słabym składnikiem listinterfejsu API i nie pamiętam, kiedy ostatni raz użyłem go w gniewie. W komentarzach wskazano mi, że ponieważ odpowiedź ta jest w dużej mierze wymieniona, należy ją uzupełnić. Niektóre zastrzeżenia dotyczące list.indexśledzenia. Prawdopodobnie warto na początku zapoznać się z dokumentacją:
list.index(x[, start[, end]])
Zwraca indeks zerowy na liście pierwszego elementu, którego wartość jest równa x . Podnosi a, ValueErrorjeśli nie ma takiego przedmiotu.
Opcjonalne argumenty początkowy i końcowy są interpretowane jak w notacji plastra i służą do ograniczenia wyszukiwania do określonej podsekwencji listy. Zwrócony indeks jest obliczany w stosunku do początku pełnej sekwencji, a nie do argumentu początkowego.
Liniowa złożoność czasowa długości listy
indexWezwanie sprawdza każdy element na liście w porządku, dopóki nie znajdzie dopasowanie. Jeśli twoja lista jest długa i nie wiesz z grubsza, gdzie na niej występuje, wyszukiwanie może stać się wąskim gardłem. W takim przypadku należy rozważyć inną strukturę danych. Pamiętaj, że jeśli z grubsza wiesz, gdzie znaleźć dopasowanie, możesz dać indexwskazówkę. Na przykład w tym fragmencie l.index(999_999, 999_990, 1_000_000)jest o około pięć rzędów wielkości szybszy niż prosty l.index(999_999), ponieważ pierwszy z nich musi przeszukać tylko 10 pozycji, a drugi - milion:
Zwraca tylko indeks pierwszego dopasowania do swojego argumentu
Wezwanie do indexprzeszukiwania listy w kolejności, aż znajdzie dopasowanie i tam się kończy. Jeśli oczekujesz, że będziesz potrzebować indeksów o większej liczbie dopasowań, powinieneś użyć zrozumienia listy lub wyrażenia generatora.
>>>[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
W większości miejsc, w których kiedyś bym używał index, teraz używam rozumienia listy lub wyrażenia generatora, ponieważ są one bardziej ogólne. Więc jeśli zastanawiasz się nad sięgnięciem po index, spójrz na te doskonałe funkcje Pythona.
Zgłasza, jeśli element nie występuje na liście
Wezwanie do indexskutkuje ValueErrorbrakiem elementu.
>>>[1,1].index(2)Traceback(most recent call last):File"<stdin>", line 1,in<module>ValueError:2isnotin list
Jeśli element może nie być obecny na liście, powinieneś albo
Najpierw sprawdź to za pomocą item in my_list(czyste, czytelne podejście) lub
Zawinąć indexpołączenie w try/exceptblok, który łapie ValueError(prawdopodobnie szybciej, przynajmniej gdy lista do przeszukania jest długa, a element jest zwykle obecny).
indeks zwraca pierwszy element, którego wartość to „bar”. Jeśli „pasek” istnieje dwa razy na liście, nigdy nie znajdziesz klucza do drugiego „paska”. Zobacz dokumentację: docs.python.org/3/tutorial/datastructures.html
mpoletto 30.01.2018
2
Jeśli szukasz tylko jednego elementu (pierwszego), okazało się, że index()jest to nieco mniej niż 90% szybciej niż zrozumienie listy względem list liczb całkowitych.
slybloty,
Jakiej struktury danych należy użyć, jeśli lista jest bardzo długa?
izhang05
@izhang: Niektóre indeksy pomocnicze, takie jak dyktat {element -> list_index}, jeśli elementy są haszowalne, a pozycja na liście ma znaczenie.
Alex Coventry
898
Jedną z rzeczy, która jest naprawdę pomocna w nauce języka Python, jest użycie interaktywnej funkcji pomocy:
>>> help(["foo","bar","baz"])Help on list object:class list(object)...|| index(...)| L.index(value,[start,[stop]])-> integer --return first index of value
|
bpython to przyjemny, przyjazny dla użytkownika sposób na czytanie dokumentów w interaktywny sposób.
goetzc
@davidavr tak, ale reszta z nas, którzy po prostu chcą google zamiast przewijać dokumenty pomocy, nie mieliby tego miłego, centralnego, uporządkowanego zestawu opcji. :)
honkaboy,
555
Większość odpowiedzi wyjaśnia, jak znaleźć pojedynczy indeks , ale ich metody nie zwracają wielu indeksów, jeśli element jest na liście wiele razy. Użyj enumerate():
for i, j in enumerate(['foo','bar','baz']):if j =='bar':print(i)
index()Funkcja zwraca tylko pierwsze wystąpienie, podczas gdyenumerate() zwraca wszystkie wystąpienia.
Jako zrozumienie listy:
[i for i, j in enumerate(['foo','bar','baz'])if j =='bar']
Oto także inne małe rozwiązanie z itertools.count()(które jest prawie takim samym podejściem jak wyliczenie):
from itertools import izip as zip, count # izip for maximum efficiency[i for i, j in zip(count(),['foo','bar','baz'])if j =='bar']
Jest to bardziej wydajne w przypadku większych list niż używanie 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
Wyliczanie działa dla mnie lepiej niż metody oparte na indeksach, ponieważ chcę zebrać indeksy ciągów za pomocą „startwith” i muszę zebrać wiele wystąpień. Czy istnieje sposób na użycie indeksu z „startwith”, że ja nie mogłem
rozgryźć
3
W moich rękach wersja wyliczeniowa jest konsekwentnie nieco szybsza. Niektóre szczegóły implementacji mogły ulec zmianie od czasu opublikowania powyższego pomiaru.
Problem pojawi się, jeśli elementu nie ma na liście. Ta funkcja obsługuje 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
Może to jednak podwoić złożoność. Czy ktoś sprawdził?
stefanct
@stefanct Złożoność czasowa jest nadal liniowa, ale będzie dwa razy iterować listę.
ApproachingDarknessFish
@ApproachingDarknessFish To właśnie miałem na myśli. Nawet jeśli pedantycznie jest to ta sama kolejność złożoności, dwukrotne powtórzenie może być poważną wadą w wielu przypadkach użycia, dlatego ją poruszyłem. I wciąż nie znamy odpowiedzi ...
stefanct
44
Wszystkie proponowane tutaj funkcje odtwarzają nieodłączne zachowanie językowe, ale zaciemniają to, co się dzieje.
[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
Po co pisać funkcję z obsługą wyjątków, jeśli język zapewnia metody umożliwiające robienie tego, co chcesz?
Trzecia metoda iteruje dwa razy na liście, prawda?
Eric Duminil
Re: „Wszystkie proponowane funkcje tutaj” : Być może w momencie pisania, ale powinieneś sprawdzić nowsze odpowiedzi, aby sprawdzić, czy nadal jest to prawda.
Peter Mortensen
41
Jeśli chcesz wszystkie indeksy, możesz użyć NumPy :
To jest najlepszy, jaki przeczytałem. Tablice numpy są znacznie wydajniejsze niż listy Python. Jeśli lista jest krótka, nie ma problemu z utworzeniem jej kopii z listy Pythona, jeśli nie jest, to być może deweloper powinien rozważyć przechowywanie elementów w tablicy numpy.
Athanassios
35
Znajdowanie indeksu elementu na podstawie listy zawierającej go w Pythonie
W przypadku listy ["foo", "bar", "baz"]i elementu na liście "bar", jaki jest najczystszy sposób na uzyskanie indeksu (1) w Pythonie?
Jasne, istnieje metoda index, która zwraca indeks pierwszego wystąpienia:
>>> l =["foo","bar","baz"]>>> l.index('bar')1
Istnieje kilka problemów z tą metodą:
jeśli wartości nie ma na liście, otrzymasz ValueError
jeśli na liście znajduje się więcej niż jedna wartość, indeks otrzymujesz tylko dla pierwszej
Brak wartości
Jeśli wartość może być brakująca, musisz złapać ValueError.
Możesz to zrobić za pomocą takiej definicji wielokrotnego użytku:
A jeśli chcesz je na liście lub krotce, po prostu przekaż je konstruktorowi:
>>> list(series[series =='bar'].index)[1,3]
Tak, możesz również użyć listowego wyrażenia z wyliczeniem, ale moim zdaniem nie jest to tak eleganckie - robisz testy na równość w Pythonie, zamiast pozwalać na obsługę wbudowanego kodu napisanego w C:
>>>[i for i, value in enumerate(l)if value =='bar'][1,3]
Problem XY polega na pytaniu o próbę rozwiązania, a nie o faktyczny problem.
Jak myślisz, dlaczego indeks ma dany element na liście?
Jeśli znasz już wartość, dlaczego obchodzi Cię, gdzie znajduje się na liście?
Jeśli nie ma tej wartości, wyłapywanie jej ValueErrorjest raczej pełne - i wolę tego unikać.
I tak zwykle iteruję listę, więc zwykle trzymam wskaźnik do każdej interesującej informacji, uzyskując indeks z wyliczeniem.
Jeśli mungujesz dane, prawdopodobnie powinieneś używać pand - które mają o wiele bardziej eleganckie narzędzia niż czyste obejścia Pythona, które pokazałem.
Sam nie pamiętam potrzeby list.index. Jednak przejrzałem standardową bibliotekę Python i dostrzegłem jej doskonałe zastosowania.
Jest wiele, wiele zastosowań idlelib , dla GUI i parsowania tekstu.
The keyword Moduł wykorzystuje to, aby znaleźć znaczniki komentarza w module automatycznie regenerować listę słów kluczowych w nim za pośrednictwem metaprogramowanie.
W Lib / mailbox.py wydaje się, że używa go jak uporządkowane mapowanie:
key_list[key_list.index(old)]= new
i
del key_list[key_list.index(key)]
W Lib / http / cookiejar.py wydaje się być używany do uzyskania następnego miesiąca:
mon = MONTHS_LOWER.index(mon.lower())+1
W pliku Lib / tarfile.py podobnym do distutils, aby uzyskać kawałek do elementu:
members = members[:members.index(tarinfo)]
W Lib / pickletools.py:
numtopop = before.index(markobject)
Wydaje się, że te zastosowania mają wspólną cechę: wydaje się, że działają na listach ograniczonych rozmiarów (ważne ze względu na czas wyszukiwania O (n) dla list.index ) i są one najczęściej używane podczas analizowania (i interfejsu użytkownika w przypadku bezczynności).
Chociaż istnieją przypadki użycia, są one dość rzadkie. Jeśli znajdziesz tę odpowiedź, zadaj sobie pytanie, czy to, co robisz, jest najbardziej bezpośrednim użyciem narzędzi dostarczonych przez język dla twojego przypadku użycia.
Uzyskiwanie wszystkich wystąpień i pozycji jednego lub więcej (identycznych) elementów na liście
Za pomocą enumerate (alist) możesz zapisać pierwszy element (n), który jest indeksem listy, gdy element x jest równy temu, czego szukasz.
>>> alist =['foo','spam','egg','foo']>>> foo_indexes =[n for n,x in enumerate(alist)if x=='foo']>>> foo_indexes
[0,3]>>>
Zróbmy naszą funkcję findindex
Ta funkcja przyjmuje argument i listę jako argumenty i zwraca pozycję elementu na liście, jak widzieliśmy wcześniej.
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"))
Wynik
[1,3,5,7]
Prosty
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]>>>
... jak potwierdzenie istnienia elementu przed uzyskaniem indeksu. Zaletą tego podejścia jest to, że funkcja zawsze zwraca listę indeksów - nawet jeśli jest to pusta lista. Działa również z łańcuchami.
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')
Po wklejeniu do interaktywnego okna python:
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]>>>
Aktualizacja
Po kolejnym roku head-downowego rozwoju Pythona jestem nieco zawstydzony moją oryginalną odpowiedzią, więc aby ustawić rekord, z pewnością można użyć powyższego kodu; jednak o wiele bardziej idiomatycznym sposobem uzyskania tego samego zachowania byłoby użycie funkcji list list, wraz z funkcją enumerate ().
Coś takiego:
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')
Co po wklejeniu do interaktywnego okna pythona daje:
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]>>>
A teraz, po przejrzeniu tego pytania i wszystkich odpowiedzi, zdaję sobie sprawę, że dokładnie to zasugerował FMc w swojej wcześniejszej odpowiedzi . W chwili, gdy pierwotnie odpowiedziałem na to pytanie, nawet nie widziałem tej odpowiedzi, ponieważ jej nie rozumiałem. Mam nadzieję, że mój nieco bardziej szczegółowy przykład pomoże w zrozumieniu.
Jeśli powyższy pojedynczy wiersz kodu nadal nie ma dla ciebie sensu, bardzo polecam „zrozumienie listy Pythona” Google i poświęcenie kilku minut na zapoznanie się. To tylko jedna z wielu potężnych funkcji, które sprawiają, że korzystanie z Pythona do tworzenia kodu jest przyjemnością.
Wariant odpowiedzi od FMc i user7177 da dykt, który może zwrócić wszystkie indeksy dla dowolnego wpisu:
>>> 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]}>>>
Możesz również użyć tego jako jednej linijki, aby uzyskać wszystkie indeksy dla jednego wpisu. Nie ma gwarancji wydajności, chociaż użyłem set (a), aby zmniejszyć liczbę wywołań lambda.
To rozwiązanie nie jest tak skuteczne jak inne, ale jeśli jesteś początkujący i wiesz tylko o forpętlach, nadal możesz znaleźć pierwszy indeks elementu, unikając ValueError:
def find_element(p,t):
i =0for e in p:if e == t:return i
else:
i +=1return-1
[i for i, j inumerate (stóg siana), jeśli j == 'igła'] jest bardziej zwarta i czytelna, tak myślę.
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)
To dotyczy, jeśli ciąg również nie znajduje się na liście, jeśli nie ma go na liście location = -1
index()Metoda Python zgłasza błąd, jeśli element nie został znaleziony. Zamiast tego możesz uczynić go podobnym do indexOf()funkcji JavaScript, która zwraca, -1jeśli element nie został znaleziony:
try:
index = array.index('search_keyword')exceptValueError:
index =-1
Jednak JavaScript ma filozofię, że dziwne wyniki są lepsze od błędów, więc ma to sens, aby powrócić -1, ale w Pythonie, może to uczynić trudno wyśledzić błąd, ponieważ -1 zwraca element z końca listy.
Ta odpowiedź czuje się jak w domu dla Scala/ funkcjonalnych programowania entuzjastów
Y2K-Shubham
3
Nadajmy nazwę lstposiadanej liście. Można przekonwertować listę lstna numpy array. A następnie użyj numpy.where, aby uzyskać indeks wybranego elementu na liście. Poniżej przedstawiono sposób jego wdrożenia.
import numpy as np
lst =["foo","bar","baz"]#lst: : 'list' data typeprint np.where( np.array(lst)=='bar')[0][0]>>>1
Jeśli masz zamiar znaleźć indeks raz, użycie metody „index” jest w porządku. Jeśli jednak zamierzasz przeszukiwać swoje dane więcej niż raz, polecam użycie modułu bisect . Należy pamiętać, że przy użyciu danych modułu dwusiecznego należy posortować. Więc sortujesz dane raz, a potem możesz użyć dwusiecznej. Korzystanie z modułu dwusiecznego na mojej maszynie jest około 20 razy szybsze niż przy użyciu metody indeksowania.
Oto przykład kodu używającego składni Python 3.8 i nowszej:
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}")
W wielu odpowiedziach wspomniano o wbudowanej metodzie list.index(item) metodą jest algorytm O (n). W porządku, jeśli musisz to zrobić raz. Ale jeśli musisz uzyskiwać dostęp do indeksów elementów wiele razy, sensowniej jest najpierw utworzyć słownik (O (n)) par indeks-element, a następnie uzyskać dostęp do indeksu w O (1) za każdym razem, gdy potrzebujesz to.
Jeśli masz pewność, że elementy na liście nigdy się nie powtarzają, możesz łatwo:
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.
Jeśli możesz mieć zduplikowane elementy i musisz zwrócić wszystkie ich indeksy:
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]
moim zdaniem ["foo", "bar", "baz"].index("bar")jest dobry, ale to nie wystarczy! Bo jeśli „słownika” nie ma w słowniku, ValueErrorpodniesiono. Możesz więc użyć tej funkcji:
Nie używaj tego, ponieważ l = [1, 2]; find_index(l, 3)wróci -1i l[find_index(l, 3)]wróci 2. -1 to zła rzecz do zwrócenia, po prostu zwróć Brak.
Daniel Stracaboško
-1 to umowa, którą możesz zwrócić, co tylko chcesz, ale staraj się używać mniejszej wartości None w swoich programach, ponieważ None lub Null w komunikacji Twojego programu z innymi programami, takimi jak strony z Androidem i PHP, mogą spowodować zerwanie programu, na przykład możesz zwrócić wartość NULL w JSON a aplikacja telefonu do witryny zostanie zamknięta lub zwróci błąd 500 (wewnętrzny błąd serwera).
"bar"
, [2] Wszystkie indeksy"bar"
?Odpowiedzi:
Odniesienie: Struktury danych> Więcej o listach
Następują zastrzeżenia
Zauważ, że chociaż jest to być może najczystszy sposób na udzielenie odpowiedzi na zadane pytanie ,
index
jest raczej słabym składnikiemlist
interfejsu API i nie pamiętam, kiedy ostatni raz użyłem go w gniewie. W komentarzach wskazano mi, że ponieważ odpowiedź ta jest w dużej mierze wymieniona, należy ją uzupełnić. Niektóre zastrzeżenia dotyczącelist.index
śledzenia. Prawdopodobnie warto na początku zapoznać się z dokumentacją:Liniowa złożoność czasowa długości listy
index
Wezwanie sprawdza każdy element na liście w porządku, dopóki nie znajdzie dopasowanie. Jeśli twoja lista jest długa i nie wiesz z grubsza, gdzie na niej występuje, wyszukiwanie może stać się wąskim gardłem. W takim przypadku należy rozważyć inną strukturę danych. Pamiętaj, że jeśli z grubsza wiesz, gdzie znaleźć dopasowanie, możesz daćindex
wskazówkę. Na przykład w tym fragmenciel.index(999_999, 999_990, 1_000_000)
jest o około pięć rzędów wielkości szybszy niż prostyl.index(999_999)
, ponieważ pierwszy z nich musi przeszukać tylko 10 pozycji, a drugi - milion:Zwraca tylko indeks pierwszego dopasowania do swojego argumentu
Wezwanie do
index
przeszukiwania listy w kolejności, aż znajdzie dopasowanie i tam się kończy. Jeśli oczekujesz, że będziesz potrzebować indeksów o większej liczbie dopasowań, powinieneś użyć zrozumienia listy lub wyrażenia generatora.W większości miejsc, w których kiedyś bym używał
index
, teraz używam rozumienia listy lub wyrażenia generatora, ponieważ są one bardziej ogólne. Więc jeśli zastanawiasz się nad sięgnięciem poindex
, spójrz na te doskonałe funkcje Pythona.Zgłasza, jeśli element nie występuje na liście
Wezwanie do
index
skutkujeValueError
brakiem elementu.Jeśli element może nie być obecny na liście, powinieneś albo
item in my_list
(czyste, czytelne podejście) lubindex
połączenie wtry/except
blok, który łapieValueError
(prawdopodobnie szybciej, przynajmniej gdy lista do przeszukania jest długa, a element jest zwykle obecny).źródło
index()
jest to nieco mniej niż 90% szybciej niż zrozumienie listy względem list liczb całkowitych.Jedną z rzeczy, która jest naprawdę pomocna w nauce języka Python, jest użycie interaktywnej funkcji pomocy:
co często doprowadzi Cię do poszukiwanej metody.
źródło
Większość odpowiedzi wyjaśnia, jak znaleźć pojedynczy indeks , ale ich metody nie zwracają wielu indeksów, jeśli element jest na liście wiele razy. Użyj
enumerate()
:index()
Funkcja zwraca tylko pierwsze wystąpienie, podczas gdyenumerate()
zwraca wszystkie wystąpienia.Jako zrozumienie listy:
Oto także inne małe rozwiązanie z
itertools.count()
(które jest prawie takim samym podejściem jak wyliczenie):Jest to bardziej wydajne w przypadku większych list niż używanie
enumerate()
:źródło
Aby uzyskać wszystkie indeksy:
źródło
index()
zwraca pierwszy indeks wartości!źródło
Problem pojawi się, jeśli elementu nie ma na liście. Ta funkcja obsługuje problem:
źródło
źródło
Musisz ustawić warunek, aby sprawdzić, czy szukany element znajduje się na liście
źródło
Wszystkie proponowane tutaj funkcje odtwarzają nieodłączne zachowanie językowe, ale zaciemniają to, co się dzieje.
Po co pisać funkcję z obsługą wyjątków, jeśli język zapewnia metody umożliwiające robienie tego, co chcesz?
źródło
Jeśli chcesz wszystkie indeksy, możesz użyć NumPy :
To jasne, czytelne rozwiązanie.
źródło
Jasne, istnieje metoda index, która zwraca indeks pierwszego wystąpienia:
Istnieje kilka problemów z tą metodą:
ValueError
Brak wartości
Jeśli wartość może być brakująca, musisz złapać
ValueError
.Możesz to zrobić za pomocą takiej definicji wielokrotnego użytku:
I użyj tego w ten sposób:
Wadą tego jest to, że prawdopodobnie będziesz musiał sprawdzić, czy zwrócona wartość
is
lubis not
Brak:Więcej niż jedna wartość na liście
Jeśli możesz mieć więcej wystąpień, nie otrzymasz pełnych informacji z
list.index
:Możesz wyliczyć do listy ze zrozumieniem indeksy:
Jeśli nie masz żadnych wystąpień, możesz to sprawdzić za pomocą logicznej kontroli wyniku lub po prostu nie rób nic, jeśli przejdziesz przez wyniki:
Lepsze mungowanie danych dzięki pandom
Jeśli masz pandy, możesz łatwo uzyskać te informacje za pomocą obiektu serii:
Kontrola porównawcza zwróci szereg wartości logicznych:
Przekaż tę serię logów do serii za pomocą notacji indeksu dolnego, a otrzymasz tylko pasujących członków:
Jeśli chcesz tylko indeksy, atrybut index zwraca serię liczb całkowitych:
A jeśli chcesz je na liście lub krotce, po prostu przekaż je konstruktorowi:
Tak, możesz również użyć listowego wyrażenia z wyliczeniem, ale moim zdaniem nie jest to tak eleganckie - robisz testy na równość w Pythonie, zamiast pozwalać na obsługę wbudowanego kodu napisanego w C:
Czy to problem XY ?
Jak myślisz, dlaczego indeks ma dany element na liście?
Jeśli znasz już wartość, dlaczego obchodzi Cię, gdzie znajduje się na liście?
Jeśli nie ma tej wartości, wyłapywanie jej
ValueError
jest raczej pełne - i wolę tego unikać.I tak zwykle iteruję listę, więc zwykle trzymam wskaźnik do każdej interesującej informacji, uzyskując indeks z wyliczeniem.
Jeśli mungujesz dane, prawdopodobnie powinieneś używać pand - które mają o wiele bardziej eleganckie narzędzia niż czyste obejścia Pythona, które pokazałem.
Sam nie pamiętam potrzeby
list.index
. Jednak przejrzałem standardową bibliotekę Python i dostrzegłem jej doskonałe zastosowania.Jest wiele, wiele zastosowań
idlelib
, dla GUI i parsowania tekstu.The
keyword
Moduł wykorzystuje to, aby znaleźć znaczniki komentarza w module automatycznie regenerować listę słów kluczowych w nim za pośrednictwem metaprogramowanie.W Lib / mailbox.py wydaje się, że używa go jak uporządkowane mapowanie:
i
W Lib / http / cookiejar.py wydaje się być używany do uzyskania następnego miesiąca:
W pliku Lib / tarfile.py podobnym do distutils, aby uzyskać kawałek do elementu:
W Lib / pickletools.py:
Wydaje się, że te zastosowania mają wspólną cechę: wydaje się, że działają na listach ograniczonych rozmiarów (ważne ze względu na czas wyszukiwania O (n) dla
list.index
) i są one najczęściej używane podczas analizowania (i interfejsu użytkownika w przypadku bezczynności).Chociaż istnieją przypadki użycia, są one dość rzadkie. Jeśli znajdziesz tę odpowiedź, zadaj sobie pytanie, czy to, co robisz, jest najbardziej bezpośrednim użyciem narzędzi dostarczonych przez język dla twojego przypadku użycia.
źródło
Wszystkie indeksy z
zip
funkcją:źródło
Uzyskiwanie wszystkich wystąpień i pozycji jednego lub więcej (identycznych) elementów na liście
Za pomocą enumerate (alist) możesz zapisać pierwszy element (n), który jest indeksem listy, gdy element x jest równy temu, czego szukasz.
Zróbmy naszą funkcję findindex
Ta funkcja przyjmuje argument i listę jako argumenty i zwraca pozycję elementu na liście, jak widzieliśmy wcześniej.
Wynik
Prosty
Wynik:
źródło
Po prostu możesz iść z
źródło
Inna opcja
źródło
A teraz coś z zupełnie innej beczki...
... jak potwierdzenie istnienia elementu przed uzyskaniem indeksu. Zaletą tego podejścia jest to, że funkcja zawsze zwraca listę indeksów - nawet jeśli jest to pusta lista. Działa również z łańcuchami.
Po wklejeniu do interaktywnego okna python:
Aktualizacja
Po kolejnym roku head-downowego rozwoju Pythona jestem nieco zawstydzony moją oryginalną odpowiedzią, więc aby ustawić rekord, z pewnością można użyć powyższego kodu; jednak o wiele bardziej idiomatycznym sposobem uzyskania tego samego zachowania byłoby użycie funkcji list list, wraz z funkcją enumerate ().
Coś takiego:
Co po wklejeniu do interaktywnego okna pythona daje:
A teraz, po przejrzeniu tego pytania i wszystkich odpowiedzi, zdaję sobie sprawę, że dokładnie to zasugerował FMc w swojej wcześniejszej odpowiedzi . W chwili, gdy pierwotnie odpowiedziałem na to pytanie, nawet nie widziałem tej odpowiedzi, ponieważ jej nie rozumiałem. Mam nadzieję, że mój nieco bardziej szczegółowy przykład pomoże w zrozumieniu.
Jeśli powyższy pojedynczy wiersz kodu nadal nie ma dla ciebie sensu, bardzo polecam „zrozumienie listy Pythona” Google i poświęcenie kilku minut na zapoznanie się. To tylko jedna z wielu potężnych funkcji, które sprawiają, że korzystanie z Pythona do tworzenia kodu jest przyjemnością.
źródło
Wariant odpowiedzi od FMc i user7177 da dykt, który może zwrócić wszystkie indeksy dla dowolnego wpisu:
Możesz również użyć tego jako jednej linijki, aby uzyskać wszystkie indeksy dla jednego wpisu. Nie ma gwarancji wydajności, chociaż użyłem set (a), aby zmniejszyć liczbę wywołań lambda.
źródło
To rozwiązanie nie jest tak skuteczne jak inne, ale jeśli jesteś początkujący i wiesz tylko o
for
pętlach, nadal możesz znaleźć pierwszy indeks elementu, unikając ValueError:źródło
Znajdowanie indeksu pozycji x na liście L:
źródło
Ponieważ listy w języku Python są zerowane, możemy użyć wbudowanej funkcji zip w następujący sposób:
gdzie „stóg siana” to lista, a „igła” to pozycja, której należy szukać.
(Uwaga: tutaj iterujemy za pomocą i, aby uzyskać indeksy, ale jeśli musimy skupić się na elementach, możemy przełączyć na j.)
źródło
To dotyczy, jeśli ciąg również nie znajduje się na liście, jeśli nie ma go na liście
location = -1
źródło
index()
Metoda Python zgłasza błąd, jeśli element nie został znaleziony. Zamiast tego możesz uczynić go podobnym doindexOf()
funkcji JavaScript, która zwraca,-1
jeśli element nie został znaleziony:źródło
Jest na to bardziej funkcjonalna odpowiedź.
Bardziej ogólna forma:
źródło
Scala
/ funkcjonalnych programowania entuzjastówNadajmy nazwę
lst
posiadanej liście. Można przekonwertować listęlst
nanumpy array
. A następnie użyj numpy.where, aby uzyskać indeks wybranego elementu na liście. Poniżej przedstawiono sposób jego wdrożenia.źródło
Dla osób pochodzących z innego języka, takiego jak ja, być może za pomocą prostej pętli łatwiej jest go zrozumieć i używać:
Jestem wdzięczny za Więc co dokładnie robi wyliczanie? . To pomogło mi zrozumieć.
źródło
Jeśli masz zamiar znaleźć indeks raz, użycie metody „index” jest w porządku. Jeśli jednak zamierzasz przeszukiwać swoje dane więcej niż raz, polecam użycie modułu bisect . Należy pamiętać, że przy użyciu danych modułu dwusiecznego należy posortować. Więc sortujesz dane raz, a potem możesz użyć dwusiecznej. Korzystanie z modułu dwusiecznego na mojej maszynie jest około 20 razy szybsze niż przy użyciu metody indeksowania.
Oto przykład kodu używającego składni Python 3.8 i nowszej:
Wynik:
źródło
Jeśli wydajność ma znaczenie:
W wielu odpowiedziach wspomniano o wbudowanej metodzie
list.index(item)
metodą jest algorytm O (n). W porządku, jeśli musisz to zrobić raz. Ale jeśli musisz uzyskiwać dostęp do indeksów elementów wiele razy, sensowniej jest najpierw utworzyć słownik (O (n)) par indeks-element, a następnie uzyskać dostęp do indeksu w O (1) za każdym razem, gdy potrzebujesz to.Jeśli masz pewność, że elementy na liście nigdy się nie powtarzają, możesz łatwo:
Jeśli możesz mieć zduplikowane elementy i musisz zwrócić wszystkie ich indeksy:
źródło
Jak wskazuje @TerryA, wiele odpowiedzi omawia, jak znaleźć jeden indeks.
more_itertools
to biblioteka innej firmy z narzędziami do lokalizowania wielu indeksów w iterowalnym.Dany
Kod
Znajdź wskaźniki wielu obserwacji:
Przetestuj wiele elementów:
Zobacz także więcej opcji za pomocą
more_itertools.locate
. Zainstaluj przez> pip install more_itertools
.źródło
za pomocą słownika, gdzie najpierw przetworz listę, a następnie dodaj do niej indeks
źródło
moim zdaniem
["foo", "bar", "baz"].index("bar")
jest dobry, ale to nie wystarczy! Bo jeśli „słownika” nie ma w słowniku,ValueError
podniesiono. Możesz więc użyć tej funkcji:a wynikiem jest:
a jeśli nazwa nie była w arr, funkcja zwraca -1. na przykład:
źródło
l = [1, 2]; find_index(l, 3)
wróci-1
il[find_index(l, 3)]
wróci2
. -1 to zła rzecz do zwrócenia, po prostu zwróć Brak.