Dato un elenco ["foo", "bar", "baz"]
e un elemento nell'elenco "bar"
, come posso ottenere il suo indice ( 1
) in Python?
Dato un elenco ["foo", "bar", "baz"]
e un elemento nell'elenco "bar"
, come posso ottenere il suo indice ( 1
) in Python?
Risposte:
>>> ["foo", "bar", "baz"].index("bar")
1
Riferimento: Strutture dati> Altro sugli elenchi
Si noti che mentre questo è forse il modo più pulito per rispondere alla domanda come posta , index
è un componente piuttosto debole list
dell'API e non ricordo l'ultima volta che l'ho usato con rabbia. Mi è stato sottolineato nei commenti che, poiché questa risposta è fortemente referenziata, dovrebbe essere resa più completa. list.index
Seguono alcune avvertenze . Probabilmente vale la pena dare un'occhiata inizialmente alla documentazione per questo:
list.index(x[, start[, end]])
Restituisce l'indice in base zero nell'elenco del primo elemento il cui valore è uguale a x . Genera un
ValueError
se non esiste tale oggetto.Gli argomenti facoltativi inizio e fine vengono interpretati come nella notazione della sezione e vengono utilizzati per limitare la ricerca a una particolare sottosequenza dell'elenco. L'indice restituito viene calcolato relativamente all'inizio dell'intera sequenza anziché all'argomento iniziale.
Una index
chiamata controlla ogni elemento dell'elenco in ordine, fino a quando non trova una corrispondenza. Se la tua lista è lunga e non sai all'incirca dove si trova nell'elenco, questa ricerca potrebbe diventare un collo di bottiglia. In tal caso, è necessario considerare una struttura dati diversa. Nota che se sai approssimativamente dove trovare la partita, puoi dare index
un suggerimento. Ad esempio, in questo frammento, l.index(999_999, 999_990, 1_000_000)
è circa cinque ordini di grandezza più veloce di quello diritto l.index(999_999)
, perché il primo deve solo cercare 10 voci, mentre il secondo cerca un milione:
>>> 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
Una chiamata per index
cercare l'elenco in ordine fino a quando non trova una corrispondenza e si ferma lì. Se si prevede di aver bisogno di indici di più corrispondenze, è necessario utilizzare una comprensione dell'elenco o un'espressione del generatore.
>>> [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
La maggior parte dei luoghi in cui una volta avrei usato index
, ora uso una comprensione dell'elenco o un'espressione del generatore perché sono più generici. Quindi, se stai pensando di cercare index
, dai un'occhiata a queste eccellenti funzionalità di Python.
Una chiamata a index
genera un ValueError
se l'elemento non è presente.
>>> [1, 1].index(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: 2 is not in list
Se l'elemento potrebbe non essere presente nell'elenco, dovresti farlo anche tu
item in my_list
(approccio pulito e leggibile) oindex
chiamata in un try/except
blocco che cattura ValueError
(probabilmente più veloce, almeno quando l'elenco da cercare è lungo e l'elemento è solitamente presente).index()
è poco meno del 90% più veloce della comprensione dell'elenco rispetto agli elenchi di numeri interi.
Una cosa che è veramente utile nell'apprendimento di Python è l'uso della funzione di aiuto interattiva:
>>> help(["foo", "bar", "baz"])
Help on list object:
class list(object)
...
|
| index(...)
| L.index(value, [start, [stop]]) -> integer -- return first index of value
|
che spesso ti condurrà al metodo che stai cercando.
La maggior parte delle risposte spiega come trovare un singolo indice , ma i loro metodi non restituiscono più indici se l'elemento è nell'elenco più volte. Utilizzare enumerate()
:
for i, j in enumerate(['foo', 'bar', 'baz']):
if j == 'bar':
print(i)
La index()
funzione restituisce solo la prima occorrenza, mentre enumerate()
restituisce tutte le occorrenze.
Come una lista di comprensione:
[i for i, j in enumerate(['foo', 'bar', 'baz']) if j == 'bar']
Ecco anche un'altra piccola soluzione con itertools.count()
(che è praticamente lo stesso approccio dell'enumerazione):
from itertools import izip as zip, count # izip for maximum efficiency
[i for i, j in zip(count(), ['foo', 'bar', 'baz']) if j == 'bar']
Questo è più efficiente per elenchi più grandi rispetto all'uso di 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
Per ottenere tutti gli indici:
indexes = [i for i,x in enumerate(xs) if x == 'foo']
index()
restituisce il primo indice di valore!
| indice (...)
| L.index (value, [start, [stop]]) -> intero - restituisce il primo indice di valore
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"])
Si verificherà un problema se l'elemento non è nell'elenco. Questa funzione gestisce il problema:
# 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
a = ["foo","bar","baz",'bar','any','much']
indexes = [index for index in range(len(a)) if a[index] == 'bar']
Devi impostare una condizione per verificare se l'elemento che stai cercando è nell'elenco
if 'your_element' in mylist:
print mylist.index('your_element')
else:
print None
Tutte le funzioni proposte qui riproducono comportamenti linguistici intrinseci ma oscurano ciò che sta accadendo.
[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
Perché scrivere una funzione con gestione delle eccezioni se la lingua fornisce i metodi per fare ciò che si desidera?
Se vuoi tutti gli indici, puoi usare 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),)
È una soluzione chiara e leggibile.
Trovare l'indice di un elemento dato un elenco che lo contiene in Python
Per un elenco
["foo", "bar", "baz"]
e un elemento nell'elenco"bar"
, qual è il modo più pulito per ottenere il suo indice (1) in Python?
Bene, certo, c'è il metodo index, che restituisce l'indice della prima occorrenza:
>>> l = ["foo", "bar", "baz"]
>>> l.index('bar')
1
Esistono un paio di problemi con questo metodo:
ValueError
Se il valore potrebbe mancare, è necessario catturare il ValueError
.
Puoi farlo con una definizione riutilizzabile come questa:
def index(a_list, value):
try:
return a_list.index(value)
except ValueError:
return None
E usalo in questo modo:
>>> print(index(l, 'quux'))
None
>>> print(index(l, 'bar'))
1
E il rovescio della medaglia di questo è che probabilmente avrai un controllo per se il valore restituito is
o is not
Nessuno:
result = index(a_list, value)
if result is not None:
do_something(result)
Se potessi avere più ricorrenze, non otterrai informazioni complete con list.index
:
>>> l.append('bar')
>>> l
['foo', 'bar', 'baz', 'bar']
>>> l.index('bar') # nothing at index 3?
1
È possibile elencare in un elenco di comprensione degli indici:
>>> [index for index, v in enumerate(l) if v == 'bar']
[1, 3]
>>> [index for index, v in enumerate(l) if v == 'boink']
[]
Se non si verificano occorrenze, è possibile verificarlo con un controllo booleano del risultato o semplicemente non fare nulla se si passa in rassegna i risultati:
indexes = [index for index, v in enumerate(l) if v == 'boink']
for index in indexes:
do_something(index)
Se hai i panda, puoi facilmente ottenere queste informazioni con un oggetto Series:
>>> import pandas as pd
>>> series = pd.Series(l)
>>> series
0 foo
1 bar
2 baz
3 bar
dtype: object
Un controllo comparativo restituirà una serie di booleani:
>>> series == 'bar'
0 False
1 True
2 False
3 True
dtype: bool
Passa quella serie di booleani alla serie tramite notazione in pedice e otterrai solo i membri corrispondenti:
>>> series[series == 'bar']
1 bar
3 bar
dtype: object
Se vuoi solo gli indici, l'attributo index restituisce una serie di numeri interi:
>>> series[series == 'bar'].index
Int64Index([1, 3], dtype='int64')
E se li vuoi in un elenco o tupla, passali al costruttore:
>>> list(series[series == 'bar'].index)
[1, 3]
Sì, potresti usare anche una comprensione dell'elenco con enumerate, ma secondo me non è così elegante - stai facendo dei test per l'uguaglianza in Python, invece di lasciare che il codice incorporato scritto in C lo gestisca:
>>> [i for i, value in enumerate(l) if value == 'bar']
[1, 3]
Il problema XY è chiedere la tua soluzione tentata piuttosto che il tuo problema reale.
Perché pensi di aver bisogno dell'indice dato un elemento in un elenco?
Se conosci già il valore, perché ti importa dove si trova in un elenco?
Se il valore non è presente, la cattura ValueError
è piuttosto dettagliata - e preferisco evitarlo.
Di solito sto ripetendo l'elenco, quindi di solito terrò un puntatore a qualsiasi informazione interessante, ottenendo l' indice con enumerato.
Se stai mungendo i dati, dovresti probabilmente usare i panda, che hanno strumenti molto più eleganti dei semplici soluzioni Python che ho mostrato.
Non ricordo di aver bisogno di list.index
me stesso. Tuttavia, ho esaminato la libreria standard di Python e ne vedo alcuni eccellenti usi.
Ci sono molti, molti usi per esso in idlelib
, per la GUI e l'analisi del testo.
Il keyword
modulo lo utilizza per trovare marcatori di commento nel modulo per rigenerare automaticamente l'elenco di parole chiave in esso tramite metaprogrammazione.
In Lib / mailbox.py sembra usarlo come una mappatura ordinata:
key_list[key_list.index(old)] = new
e
del key_list[key_list.index(key)]
In Lib / http / cookiejar.py, sembra essere usato per ottenere il mese successivo:
mon = MONTHS_LOWER.index(mon.lower())+1
In Lib / tarfile.py simile a distutils per ottenere una sezione fino a un elemento:
members = members[:members.index(tarinfo)]
In Lib / pickletools.py:
numtopop = before.index(markobject)
Ciò che questi usi sembrano avere in comune è che sembrano operare su elenchi di dimensioni vincolate (importante a causa del tempo di ricerca O (n) per list.index
), e sono principalmente usati nell'analisi (e nell'interfaccia utente nel caso di Idle).
Mentre ci sono casi d'uso per questo, sono abbastanza rari. Se ti trovi in cerca di questa risposta, chiediti se quello che stai facendo è l'uso più diretto degli strumenti forniti dalla lingua per il tuo caso d'uso.
Tutti gli indici con la zip
funzione:
get_indexes = lambda x, xs: [i for (y, i) in zip(xs, range(len(xs))) if x == y]
print get_indexes(2, [1, 2, 3, 4, 5, 6, 3, 2, 3, 2])
print get_indexes('f', 'xsfhhttytffsafweef')
Con enumerate (alist) puoi memorizzare il primo elemento (n) che è l'indice dell'elenco quando l'elemento x è uguale a quello che cerchi.
>>> alist = ['foo', 'spam', 'egg', 'foo']
>>> foo_indexes = [n for n,x in enumerate(alist) if x=='foo']
>>> foo_indexes
[0, 3]
>>>
Questa funzione prende l'oggetto e l'elenco come argomenti e restituisce la posizione dell'oggetto nell'elenco, come abbiamo visto prima.
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"))
Produzione
[1, 3, 5, 7]
for n, i in enumerate([1, 2, 3, 4, 1]):
if i == 1:
print(n)
Produzione:
0
4
Un'altra opzione
>>> 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]
>>>
... come confermare l'esistenza dell'articolo prima di ottenere l'indice. La cosa bella di questo approccio è che la funzione restituisce sempre un elenco di indici, anche se è un elenco vuoto. Funziona anche con le stringhe.
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')
Quando incollato in una finestra interattiva di 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]
>>>
Dopo un altro anno di sviluppo di Python a testa in giù, sono un po 'imbarazzato dalla mia risposta originale, quindi per mettere le cose in chiaro, si può certamente usare il codice sopra; tuttavia, il modo molto più idiomatico di ottenere lo stesso comportamento sarebbe utilizzare la comprensione dell'elenco, insieme alla funzione enumerate ().
Qualcosa come questo:
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')
Che, quando incollato in una finestra interattiva di Python produce:
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]
>>>
E ora, dopo aver esaminato questa domanda e tutte le risposte, mi rendo conto che questo è esattamente ciò che FMc ha suggerito nella sua precedente risposta . All'epoca in cui avevo inizialmente risposto a questa domanda, non vedevo nemmeno quella risposta, perché non l'avevo capito. Spero che il mio esempio un po 'più dettagliato possa aiutare a capire.
Se la singola riga di codice sopra non ha ancora senso per te, ti consiglio vivamente la "comprensione dell'elenco python" di Google e dedicare qualche minuto a familiarizzare. È solo una delle tante potenti funzionalità che rendono piacevole l'utilizzo di Python per lo sviluppo di codice.
Una variante della risposta di FMc e user7177 fornirà un dict che può restituire tutti gli indici per qualsiasi voce:
>>> 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]}
>>>
Puoi anche usarlo come una riga per ottenere tutti gli indici per una singola voce. Non ci sono garanzie di efficienza, anche se ho usato set (a) per ridurre il numero di volte in cui viene chiamata lambda.
Ricerca dell'indice dell'elemento x nell'elenco L:
idx = L.index(x) if (x in L) else -1
Poiché gli elenchi Python sono basati su zero, possiamo usare la funzione integrata zip come segue:
>>> [i for i,j in zip(range(len(haystack)), haystack) if j == 'needle' ]
dove "pagliaio" è l'elenco in questione e "ago" è l'elemento da cercare.
(Nota: qui stiamo iterando usando i per ottenere gli indici, ma se dobbiamo piuttosto concentrarci sugli elementi possiamo passare a j.)
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)
Questo spiega se anche la stringa non è nell'elenco, se non è nell'elenco allora location = -1
Il index()
metodo Python genera un errore se l'elemento non è stato trovato. Quindi invece puoi renderlo simile alla indexOf()
funzione di JavaScript che restituisce -1
se l'elemento non è stato trovato:
try:
index = array.index('search_keyword')
except ValueError:
index = -1
C'è una risposta più funzionale a questo.
list(filter(lambda x: x[1]=="bar",enumerate(["foo", "bar", "baz", "bar", "baz", "bar", "a", "b", "c"])))
Forma più generica:
def get_index_of(lst, element):
return list(map(lambda x: x[0],\
(list(filter(lambda x: x[1]==element, enumerate(lst))))))
Scala
Diamo il nome lst
all'elenco che hai. Si può convertire la lista lst
in a numpy array
. E poi usa numpy.where per ottenere l'indice dell'elemento scelto nell'elenco. Di seguito è riportato il modo in cui lo implementerai.
import numpy as np
lst = ["foo", "bar", "baz"] #lst: : 'list' data type
print np.where( np.array(lst) == 'bar')[0][0]
>>> 1
Per quelli che provengono da un'altra lingua come me, forse con un semplice ciclo è più facile da capire e usarlo:
mylist = ["foo", "bar", "baz", "bar"]
newlist = enumerate(mylist)
for index, item in newlist:
if item == "bar":
print(index, item)
Sono grato per cosa fa esattamente l'enumerato? . Questo mi ha aiutato a capire.
Se hai intenzione di trovare un indice una volta, allora il metodo "index" va bene. Tuttavia, se hai intenzione di cercare i tuoi dati più di una volta, ti consiglio di utilizzare il modulo bisect . Tenere presente che è necessario ordinare i dati del modulo bisect. Quindi ordina i dati una volta e poi puoi usare bisect. L'uso del modulo bisect sulla mia macchina è circa 20 volte più veloce rispetto all'utilizzo del metodo dell'indice.
Ecco un esempio di codice che utilizza la sintassi di Python 3.8 e successive:
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}")
Produzione:
t1=0.0400, t2=0.0020, diffs t1/t2=19.60
In numerose risposte viene menzionato che il metodo di list.index(item)
metodo integrato è un algoritmo O (n). Va bene se devi eseguirlo una volta. Ma se è necessario accedere agli indici degli elementi più volte, è più sensato creare prima un dizionario (O (n)) di coppie oggetto-indice, quindi accedere all'indice su O (1) ogni volta che è necessario esso.
Se sei sicuro che gli elementi nel tuo elenco non vengano mai ripetuti, puoi facilmente:
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.
Se potresti avere elementi duplicati e devi restituire tutti i loro indici:
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]
Come indicato da @TerryA, molte risposte discutono su come trovare un indice.
more_itertools
è una libreria di terze parti con strumenti per individuare più indici all'interno di un iterabile.
Dato
import more_itertools as mit
iterable = ["foo", "bar", "baz", "ham", "foo", "bar", "baz"]
Codice
Trova indici di più osservazioni:
list(mit.locate(iterable, lambda x: x == "bar"))
# [1, 5]
Prova più elementi:
list(mit.locate(iterable, lambda x: x in {"bar", "ham"}))
# [1, 3, 5]
Vedi anche più opzioni con more_itertools.locate
. Installa tramite > pip install more_itertools
.
usando il dizionario, dove prima elabora l'elenco e quindi aggiunge l'indice
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]
secondo me ["foo", "bar", "baz"].index("bar")
va bene ma non è abbastanza! perché se "bar" non è nel dizionario, ValueError
sollevato . Quindi puoi usare questa funzione:
def find_index(arr, name):
try:
return arr.index(name)
except ValueError:
return -1
if __name__ == '__main__':
print(find_index(["foo", "bar", "baz"], "bar"))
e il risultato è:
1
e se il nome non era in arr, la funzione restituisce -1.per esempio:
print (find_index (["foo", "bar", "baz"], "fooo"))
-1
l = [1, 2]; find_index(l, 3)
ritornerebbe -1
e l[find_index(l, 3)]
ritornerebbe 2
. -1 è una cosa negativa da restituire, basta restituire None.
"bar"
, [2] Tutti gli indici di"bar"
?