Znajdowanie indeksu elementu na liście


3176

Biorąc pod uwagę listę ["foo", "bar", "baz"]i element na liście "bar", jak mogę uzyskać jego indeks ( 1) w Pythonie?


6
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.
Athanassios

Odpowiedzi:


4478
>>> ["foo", "bar", "baz"].index("bar")
1

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 , 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:

>>> 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

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: 2 is not in list

Jeśli element może nie być obecny na liście, powinieneś albo

  1. Najpierw sprawdź to za pomocą item in my_list(czyste, czytelne podejście) lub
  2. 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).

20
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
 |

co często doprowadzi Cię do poszukiwanej metody.


2
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.
Alex Coventry

2
Na to pytanie odpowiedziano już od '11: stackoverflow.com/questions/6294179/...
Cristik


132

index()zwraca pierwszy indeks wartości!

| indeks (...)
| L.index (wartość, [start, [stop]]) -> liczba całkowita - zwraca pierwszy indeks wartości

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"])

2
A jeśli nie ma na liście?
Peter Mortensen

1
Nieistniejący przedmiot podniesie wartośćError
Nam G VU

1
Ta odpowiedź pasowałaby lepiej tutaj: stackoverflow.com/questions/6294179/...
Cristik

86

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 None

def find_element_in_list(element, list_element):
    try:
        index_element = list_element.index(element)
        return index_element
    except ValueError:
        return None


58

Musisz ustawić warunek, aby sprawdzić, czy szukany element znajduje się na liście

if 'your_element' in mylist:
    print mylist.index('your_element')
else:
    print None

1
Pomaga nam to uniknąć próby złapania!
devssh,

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 else None    # 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?


9
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 :

import numpy as np

array = [1, 2, 1, 3, 4, 5, 1]
item = 1
np_array = np.array(array)
item_index = np.where(np_array==item)
print item_index
# Out: (array([0, 2, 6], dtype=int64),)

To jasne, czytelne rozwiązanie.


4
Co z listami ciągów, listami obiektów nienumerycznych itp.?
Laryx Decidua

1
Tę odpowiedź powinna być lepiej opublikowana tutaj: stackoverflow.com/questions/6294179/...
Cristik

1
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:

def index(a_list, value):
    try:
        return a_list.index(value)
    except ValueError:
        return None

I użyj tego w ten sposób:

>>> print(index(l, 'quux'))
None
>>> print(index(l, 'bar'))
1

Wadą tego jest to, że prawdopodobnie będziesz musiał sprawdzić, czy zwrócona wartość islub is notBrak:

result = index(a_list, value)
if result is not None:
    do_something(result)

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:

>>> l.append('bar')
>>> l
['foo', 'bar', 'baz', 'bar']
>>> l.index('bar')              # nothing at index 3?
1

Możesz wyliczyć do listy ze zrozumieniem indeksy:

>>> [index for index, v in enumerate(l) if v == 'bar']
[1, 3]
>>> [index for index, v in enumerate(l) if v == 'boink']
[]

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:

indexes = [index for index, v in enumerate(l) if v == 'boink']
for index in indexes:
    do_something(index)

Lepsze mungowanie danych dzięki pandom

Jeśli masz pandy, możesz łatwo uzyskać te informacje za pomocą obiektu serii:

>>> import pandas as pd
>>> series = pd.Series(l)
>>> series
0    foo
1    bar
2    baz
3    bar
dtype: object

Kontrola porównawcza zwróci szereg wartości logicznych:

>>> series == 'bar'
0    False
1     True
2    False
3     True
dtype: bool

Przekaż tę serię logów do serii za pomocą notacji indeksu dolnego, a otrzymasz tylko pasujących członków:

>>> series[series == 'bar']
1    bar
3    bar
dtype: object

Jeśli chcesz tylko indeksy, atrybut index zwraca serię liczb całkowitych:

>>> series[series == 'bar'].index
Int64Index([1, 3], dtype='int64')

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]

Czy to problem XY ?

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.



21

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)

Wynik:

0
4

1
Tę odpowiedź powinna być lepiej opublikowana tutaj: stackoverflow.com/questions/6294179/…
Cristik

16

Po prostu możesz iść z

a = [['hand', 'head'], ['phone', 'wallet'], ['lost', 'stock']]
b = ['phone', 'lost']

res = [[x[0] for x in a].index(y) for y in b]


15

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.

def indices(l, val):
    """Always returns a list containing the indices of val in the_list"""
    retval = []
    last = 0
    while val in l[last:]:
            i = l[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)
print indices(l,'bat')
print indices('abcdaababb','a')

Po wklejeniu do interaktywnego okna python:

Python 2.7.6 (v2.7.6:3a1db0d2747e, Nov 10 2013, 00:42:54) 
[GCC 4.2.1 (Apple Inc. 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:

Python 2.7.14 |Anaconda, Inc.| (default, Dec  7 2017, 11:07:58) 
[GCC 4.2.1 Compatible Clang 4.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ą.


12

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.


1
Tę odpowiedź powinna być lepiej opublikowana tutaj: stackoverflow.com/questions/6294179/…
Cristik

10

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 = 0
    for e in p:
        if e == t:
            return i
        else:
            i +=1
    return -1

9

Znajdowanie indeksu pozycji x na liście L:

idx = L.index(x) if (x in L) else -1

4
Powoduje to dwukrotne iterowanie tablicy, co może powodować problemy z wydajnością dużych tablic.
Cristik

Zgodzić się. Jeśli listy są dość długie, wybrałbym coś innego. Nie powinno to być wielkim problemem dla małych i średnich list.
Ketan

5

Ponieważ listy w języku Python są zerowane, możemy użyć wbudowanej funkcji zip w następujący sposób:

>>> [i for i,j in zip(range(len(haystack)), haystack) if j == 'needle' ]

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.)


3
[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=-1
print (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


4

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')
except ValueError:
    index = -1

5
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.
Sapphire_Brick

3

Jest na to bardziej funkcjonalna odpowiedź.

list(filter(lambda x: x[1]=="bar",enumerate(["foo", "bar", "baz", "bar", "baz", "bar", "a", "b", "c"])))

Bardziej ogólna forma:

def get_index_of(lst, element):
    return list(map(lambda x: x[0],\
       (list(filter(lambda x: x[1]==element, enumerate(lst))))))

1
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 type
print np.where( np.array(lst) == 'bar')[0][0]

>>> 1

2

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ć:

mylist = ["foo", "bar", "baz", "bar"]
newlist = enumerate(mylist)
for index, item in newlist:
  if item == "bar":
    print(index, item)

Jestem wdzięczny za Więc co dokładnie robi wyliczanie? . To pomogło mi zrozumieć.


2

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}")

Wynik:

t1=0.0400, t2=0.0020, diffs t1/t2=19.60

1

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:

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]

1

Jak wskazuje @TerryA, wiele odpowiedzi omawia, jak znaleźć jeden indeks.

more_itertoolsto biblioteka innej firmy z narzędziami do lokalizowania wielu indeksów w iterowalnym.

Dany

import more_itertools as mit


iterable = ["foo", "bar", "baz", "ham", "foo", "bar", "baz"]

Kod

Znajdź wskaźniki wielu obserwacji:

list(mit.locate(iterable, lambda x: x == "bar"))
# [1, 5]

Przetestuj wiele elementów:

list(mit.locate(iterable, lambda x: x in {"bar", "ham"}))
# [1, 3, 5]

Zobacz także więcej opcji za pomocą more_itertools.locate. Zainstaluj przez > pip install more_itertools.


0

za pomocą słownika, gdzie najpierw przetworz listę, a następnie dodaj do niej indeks

from collections import defaultdict

index_dict = defaultdict(list)    
word_list =  ['foo','bar','baz','bar','any', 'foo', 'much']

for word_index in range(len(word_list)) :
    index_dict[word_list[word_index]].append(word_index)

word_index_to_find = 'foo'       
print(index_dict[word_index_to_find])

# output :  [0, 5]

-1

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:

def find_index(arr, name):
    try:
        return arr.index(name)
    except ValueError:
        return -1

if __name__ == '__main__':
    print(find_index(["foo", "bar", "baz"], "bar"))

a wynikiem jest:

1

a jeśli nazwa nie była w arr, funkcja zwraca -1. na przykład:

print (find_index ([„foo”, „bar”, „baz”], „fooo”))

-1


1
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).
NaabNuts
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.