Encontrar o índice de um item dado uma lista que o contém em Python
para uma lista ["foo", "bar", "baz"]
e um item na lista "bar"
, Como é que consigo o seu Índice (1) em Python?
27 answers
>>> ["foo", "bar", "baz"].index("bar")
1
Referência: estruturas de dados > mais nas listas
Caveats follow
Note que embora esta seja talvez a maneira mais limpa de responder à pergunta Como perguntado, index
é um componente fraco da API, e não me lembro da última vez que a usei com raiva. Foi-me apontado nos comentários que, como esta resposta é fortemente referenciada, deveria ser mais completa. Algumas advertências sobre list.index
seguir. Provavelmente vale a pena. inicialmente a dar uma vista de olhos à Documentação:
>>> print(list.index.__doc__)
L.index(value, [start, [stop]]) -> integer -- return first index of value.
Raises ValueError if the value is not present.
Complexidade Linear de tempo na extensão da lista
Uma chamada index
verifica todos os elementos da lista por ordem, até encontrar uma correspondência. Se sua lista é longa, e você não sabe mais ou menos onde na lista ela ocorre, esta pesquisa pode se tornar um gargalo. Nesse caso, você deve considerar uma estrutura de dados diferente. Note que se souber mais ou menos onde encontrar a correspondência, poderá dar uma dica a index
. Por exemplo, neste trecho, l.index(999_999, 999_990, 1_000_000)
é aproximadamente cinco ordens de magnitude mais rápido que a reta l.index(999_999)
, porque a primeira só tem que procurar 10 entradas, enquanto a segunda procura um milhão:
>>> 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
Só devolve o índice da primeira correspondência ao seu argumento
Uma chamada para index
procura na lista em ordem até encontrar uma correspondência, e pára aí. se você espera precisar de índices de mais correspondências, você deve usar uma compreensão de lista, ou gerador expressao.
>>> [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
A maioria dos lugares onde eu já teria usado index
, eu agora uso uma compreensão de lista ou expressão geradora porque eles são mais generalizáveis. Então, se você está considerando alcançar index
, dê uma olhada nestas excelentes características python.
Atira se o elemento não estiver presente na lista
Uma chamada para index
resulta em ValueError
se o item não estiver presente.
>>> [1, 1].index(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: 2 is not in list
Se o item pode não estar presente na lista, você deve:
- verifique primeiro com
item in my_list
(abordagem limpa e legível), ou - Enrole a chamada
index
num blocotry/except
que capturaValueError
(provavelmente mais rápido, pelo menos quando a lista a procurar é longa, e o item está normalmente presente.)
Uma coisa que é realmente útil para aprender Python é usar a função de Ajuda Interativa:
>>> help(["foo", "bar", "baz"])
Help on list object:
class list(object)
...
|
| index(...)
| L.index(value, [start, [stop]]) -> integer -- return first index of value
|
O que muitas vezes o levará ao método que procura.
A maioria das respostas explica como encontrar um único índice , mas os seus métodos não devolvem múltiplos índices se o item estiver na lista várias vezes. Utilização enumerate()
:
for i, j in enumerate(['foo', 'bar', 'baz']):
if j == 'bar':
print(i)
A função index()
só devolve a primeira ocorrência, enquanto o enumerate()
devolve todas as ocorrências.
Como compreensão da lista:
[i for i, j in enumerate(['foo', 'bar', 'baz']) if j == 'bar']
Aqui está outra pequena solução com
itertools.count()
(o que é praticamente a mesma abordagem que enumerado):
from itertools import izip as zip, count # izip for maximum efficiency
[i for i, j in zip(count(), ['foo', 'bar', 'baz']) if j == 'bar']
Isto é mais eficiente para listas maiores do que usar 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
Para obter todos os índices:
indexes = [i for i,x in enumerate(xs) if x == 'foo']
index()
devolve o primeiro Índice de valor!
/ Índice(...)
/ L. índice(valor, [iniciar, [parar]]) -> inteiro -- return primeiro índice de valor
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"])
Um problema surgirá se o elemento não estiver na lista. Esta função trata da questão:
# 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']
Tem de definir uma condição para verificar se o elemento que procura está na lista
if 'your_element' in mylist:
print mylist.index('your_element')
else:
print None
[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
Por que escrever uma função com tratamento de exceção se a linguagem fornece os métodos para fazer o que você mesmo quer?
Se quiser todos os índices, então pode usar 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),)
É uma solução transparente e legível.
Encontrar o índice de um item com uma lista que o contém em Python
Para uma lista
["foo", "bar", "baz"]
e um item na lista"bar"
, Qual é a maneira mais limpa de obter o seu Índice (1) em Python?
Bem, claro, há o método do índice, que devolve o índice da primeira ocorrência:
>>> l = ["foo", "bar", "baz"]
>>> l.index('bar')
1
Há alguns problemas com este método:
- Se o valor não estiver na lista, vais ter um
ValueError
- se mais do que um dos o valor está na lista, você só obtém o índice para o primeiro
Sem valores
Se o valor pode estar em falta, tens de apanhar o ValueError
.
def index(a_list, value):
try:
return a_list.index(value)
except ValueError:
return None
E usa - o assim:
>>> print(index(l, 'quux'))
None
>>> print(index(l, 'bar'))
1
E o lado negativo disto é que provavelmente terá de verificar se o valor devolvido is
ou is not
nenhum:
result = index(a_list, value)
if result is not None:
do_something(result)
Mais de um valor na lista
Se pudesses ter mais ocorrências, você não vai obter informações completas com list.index
:
>>> l.append('bar')
>>> l
['foo', 'bar', 'baz', 'bar']
>>> l.index('bar') # nothing at index 3?
1
Pode enumerar numa lista os índices:
>>> [index for index, v in enumerate(l) if v == 'bar']
[1, 3]
>>> [index for index, v in enumerate(l) if v == 'boink']
[]
Se não tiver ocorrências, pode verificar isso com uma verificação booleana do resultado, ou simplesmente não fazer nada se repetir os resultados:
indexes = [index for index, v in enumerate(l) if v == 'boink']
for index in indexes:
do_something(index)
Melhores dados a mastigar com pandas
Se você tem pandas, pode facilmente obter esta informação com um objeto de série:
>>> import pandas as pd
>>> series = pd.Series(l)
>>> series
0 foo
1 bar
2 baz
3 bar
dtype: object
Uma comparação irá devolver uma série de booleanos:
>>> series == 'bar'
0 False
1 True
2 False
3 True
dtype: bool
Passa essa série de booleanos para a série através de uma notação subscrita, e recebes apenas os membros correspondentes:
>>> series[series == 'bar']
1 bar
3 bar
dtype: object
Se quiser apenas os índices, o atributo index devolve uma série de inteiros:
>>> series[series == 'bar'].index
Int64Index([1, 3], dtype='int64')
E se os queres numa lista ou numa tupla, passa-os ao construtor.
>>> list(series[series == 'bar'].index)
[1, 3]
Sim, você poderia usar uma compreensão de lista com enumerado também, mas isso não é tão elegante, na minha opinião-você está fazendo testes para igualdade em Python, em vez de deixar o código builtin escrito em C lidar com ele:
>>> [i for i, value in enumerate(l) if value == 'bar']
[1, 3]
Isto é um problema XY?
O problema XY é perguntar sobre a sua tentativa de solução em vez do seu problema real.
Porque achas que precisas do Índice dado um elemento numa lista?
Se já sabe o valor, porque se importa onde está numa lista?Se o valor não está lá, apanhar o {[20] } é bastante verboso - e prefiro evitar isso.
De qualquer forma, costumo estar a ler a lista, por isso vou manter um indicador para qualquer informação interessante, obtendo o índice com enumerado. Se você está munindo dados, você provavelmente deveria estar usando pandas - que tem ferramentas muito mais elegantes do que os simples workarounds Python que eu mostrei. Não me lembro de precisar de mim. No entanto, eu olhei através da Biblioteca Padrão Python, e eu vejo alguns usos excelentes para ele.Há muitos, muitos usos para ele em idlelib
, para o processamento de GUI e texto.
O módulo keyword
usa-o para encontrar marcadores de comentários no módulo para regenerar automaticamente a lista de palavras-chave através de metaprogramação.
Em Lib/mailbox.py parece estar a usá-lo como um mapeamento ordenado:
key_list[key_list.index(old)] = new
E
del key_list[key_list.index(key)]
Em Lib/http/cookiejar.py, parece ser usado para obter o próximo mês:
mon = MONTHS_LOWER.index(mon.lower())+1
Em Lib/tarfile.py semelhante aos destilados para obter um cortar para um item:
members = members[:members.index(tarinfo)]
Em Lib/pickletools.py:
numtopop = before.index(markobject)
O que estes usos parecem ter em comum é que eles parecem operar em listas de tamanhos limitados (importante por causa de o(n) Tempo de procura para list.index
), e eles são principalmente usados em análise (e UI no caso de OCI).
Embora haja casos de uso para ele, eles são bastante incomuns. Se você se encontrar procurando por esta resposta, pergunte a si mesmo se o que você está fazendo é o uso mais direto das ferramentas fornecido pela língua para o seu caso de uso.
Todos os índices com o índice zip
Função:
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')
Simplesmente podes ir com
a = [['hand', 'head'], ['phone', 'wallet'], ['lost', 'stock']]
b = ['phone', 'lost']
res = [[x[0] for x in a].index(y) for y in b]
Outra opção
>>> 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]
>>>
Uma variante da resposta do FMc e do user7177 irá dar um dict que pode devolver todos os índices para qualquer entrada:
>>> 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]}
>>>
Também pode usar isto como uma linha para obter todos os índices para uma única entrada. Não há garantias de eficiência, embora eu usei set(a) para reduzir o número de vezes que o lambda é chamado.
... Como confirmar a existência do item antes de obter o índice. A coisa boa sobre esta abordagem é que a função sempre retorna uma lista de índices -- mesmo que seja uma lista vazia. Também funciona com cordas.
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 colado numa janela python interactiva:
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]
>>>
Actualizar
Depois de mais um ano de desenvolvimento do heads-down python, estou um pouco envergonhado com a minha resposta original, por isso ... defina o registro direito, pode-se certamente usar o código acima; no entanto, a muito a maneira mais idiomática de obter o mesmo comportamento seria usar a compreensão da lista, juntamente com a função enumerate (). Algo do género: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')
O que, quando colado numa janela Interactiva em python, produz:
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 agora, depois de rever esta pergunta e todas as respostas, percebi que isto é exatamente o queFMc sugeriu no seu anterior. resposta Na altura em que originalmente respondi a esta pergunta, nem sequer a tinha visto, porque não a entendia. Espero que o meu exemplo um pouco mais descritivo ajude a compreender.
Se a única linha de código acima do still não faz sentido para si, recomendo-lhe vivamente que procure no Google 'compreensão da lista python' e tire alguns minutos para se familiarizar. É apenas um dos muitos recursos poderosos que fazem com que seja uma alegria usar Python para desenvolver codigo.
Obter todas as ocorrências e a posição de um ou mais itens (idênticos) numa lista
Com enumerate (lista) você pode armazenar o primeiro elemento (n) que é o índice da lista quando o elemento x é igual ao que você procura.
>>> alist = ['foo', 'spam', 'egg', 'foo']
>>> foo_indexes = [n for n,x in enumerate(alist) if x=='foo']
>>> foo_indexes
[0, 3]
>>>
Vamos fazer com que a nossa função seja findindex.
Esta função toma o item e a lista como argumentos e devolve a posição do item na lista, como vimos antes.
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"))
Saída
[1, 3, 5, 7]
Simples
for n, i in enumerate([1, 2, 3, 4, 1]):
if i == 1:
print(n)
Resultado:
0
4
Esta solução não é tão poderosa como as outras, mas se você é um iniciante e só sabe sobre for
loops ainda é possível encontrar o primeiro índice de um item, evitando o erro de Valor:
def find_element(p,t):
i = 0
for e in p:
if e == t:
return i
else:
i +=1
return -1
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)
Isto explica se o texto não está na lista também, se não está na lista então localização = -1
Uma vez que as listas Python são baseadas em zero, podemos usar a função ZIP built-in da seguinte forma:
>>> [i for i,j in zip(range(len(haystack)), haystack) if j == 'needle' ]
Onde " palheiro "é a lista em questão e" agulha " é o item a procurar.
(Nota: aqui estamos a iterar o uso de i para obter os índices, mas se precisarmos de nos concentrar nos itens, podemos mudar para J.)
list(filter(lambda x: x[1]=="bar",enumerate(["foo", "bar", "baz", "bar", "baz", "bar", "a", "b", "c"])))
Forma mais genérica:
def get_index_of(lst, element):
return list(map(lambda x: x[0],\
(list(filter(lambda x: x[1]==element, enumerate(lst))))))
O método Python index()
lança um erro se o item não foi encontrado, o que é uma treta!
Em vez disso, poderá torná-lo semelhante à função indexOf()
do JavaScript que devolve -1
Se o item não foi encontrado:
try:
index = array.index('search_keyword')
except ValueError:
index = -1
Encontrar o índice do item x na lista L:
idx = L.index(x) if (x in L) else -1
mylist = ["foo", "bar", "baz", "bar"]
newlist = enumerate(mylist)
for index, item in newlist:
if item == "bar":
print(index, item)
Estou grato por ... Então o que faz o enumerate exatamente?. Isso ajudou-me a entender.
Se o desempenho for preocupante:
É mencionado em numerosas respostas que o método embutido de list.index(item)
é um algoritmo O(n). Não faz mal se precisares de fazer isto uma vez. Mas se você precisa acessar os índices de elementos uma série de vezes, faz mais sentido primeiro criar um dicionário (O(n)) de pares de índice de itens, e então acessar o índice em O(1) cada vez que você precisar dele.
Se TEM a certeza de que os itens da sua lista nunca são repetidos, pode 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 tiver elementos duplicados e tiver de devolver todos os seus índices:
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]
Há duas possibilidades se a lista não tiver itens repetidos que é necessário verificar o índice de
eg: li=[10,20,30] # here need to get index of 20 means
li.index(20) # will work properly because 20 is not repeated
Se o seu significado repetido lhe dará apenas o primeiro índice
Se precisar de obter todo o índice onde o item está presente significa
eg: li=[10,20,30,20,40, 50, 10] # here need to get index of 20 means its have 2 index (1,3)
Para conseguir que você precisa fazer isso como
li=[10,20,30,20,40, 50, 10]
[i for i, e in enumerate(li) if e == 20]
Então você vai obter uma lista de índice como o / p Como [1,3]
Como indicado por @TerryA, muitas respostas discutem como encontrar um índice.
more_itertools
é uma biblioteca de terceiros com ferramentas para localizar múltiplos índices dentro de um iterável.
Dados
import more_itertools as mit
iterable = ["foo", "bar", "baz", "ham", "foo", "bar", "baz"]
Código
Encontrar índices de observações múltiplas:
list(mit.locate(iterable, lambda x: x == "bar"))
# [1, 5]
Testar vários itens:
list(mit.locate(iterable, lambda x: x in {"bar", "ham"}))
# [1, 3, 5]
Veja também Mais opções com more_itertools.locate
. Instalar via > pip install more_itertools
.