Dada uma lista ["foo", "bar", "baz"]
e um item na lista "bar"
, como obtenho seu index ( 1
) no Python?
Dada uma lista ["foo", "bar", "baz"]
e um item na lista "bar"
, como obtenho seu index ( 1
) no Python?
Respostas:
>>> ["foo", "bar", "baz"].index("bar")
1
Referência: Estruturas de Dados> Mais sobre Listas
Note-se que, enquanto esta é talvez a maneira mais limpa para responder à pergunta como pediu , index
é um componente bastante fraco da list
API, e eu não me lembro a última vez que eu usei com raiva. Nos comentários me foi indicado que, como essa resposta é fortemente referenciada, ela deve ser mais completa. Algumas advertências sobre list.index
seguir. Provavelmente vale a pena dar uma olhada inicialmente na documentação:
list.index(x[, start[, end]])
Retorne o índice baseado em zero na lista do primeiro item cujo valor é igual a x . Gera a
ValueError
se não houver esse item.Os argumentos opcionais start e end são interpretados como na notação de fatia e são usados para limitar a pesquisa a uma subsequência específica da lista. O índice retornado é calculado em relação ao início da sequência completa, em vez do argumento start.
Uma index
chamada verifica todos os elementos da lista em ordem, até encontrar uma correspondência. Se sua lista for longa e você não souber aproximadamente onde ela ocorre, essa pesquisa poderá se tornar um gargalo. Nesse caso, você deve considerar uma estrutura de dados diferente. Observe que, se você souber aproximadamente onde encontrar a correspondência, poderá dar index
uma dica. Por exemplo, neste trecho, l.index(999_999, 999_990, 1_000_000)
é aproximadamente cinco ordens de magnitude mais rápido que o direito l.index(999_999)
, porque o primeiro precisa pesquisar apenas 10 entradas, enquanto o último pesquisa 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
Uma chamada para index
pesquisar na lista em ordem até encontrar uma correspondência e parar por aí. Se você espera precisar de índices de mais correspondências, use uma compreensão de lista ou expressão geradora.
>>> [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
Na maioria dos lugares onde antes eu usaria index
, agora uso uma compreensão de lista ou expressão geradora, porque são mais generalizáveis. Portanto, se você está pensando em index
procurar, dê uma olhada nesses excelentes recursos Python.
Uma chamada para index
resultados em a 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 não estiver presente na lista, você deve
item in my_list
(abordagem limpa e legível) ouindex
chamada em um try/except
bloco que atenda ValueError
(provavelmente mais rápido, pelo menos quando a lista a pesquisar for longa e o item estiver geralmente presente).index()
é pouco menos de 90% mais rápido que a compreensão de listas em relação a listas de números inteiros.
Uma coisa que é realmente útil no aprendizado do 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 geralmente o levará ao método que você está procurando.
A maioria das respostas explica como encontrar um único índice , mas seus métodos não retornam vários índices se o item estiver na lista várias vezes. Use enumerate()
:
for i, j in enumerate(['foo', 'bar', 'baz']):
if j == 'bar':
print(i)
A index()
função retorna apenas a primeira ocorrência, enquanto enumerate()
retorna todas as ocorrências.
Como compreensão da lista:
[i for i, j in enumerate(['foo', 'bar', 'baz']) if j == 'bar']
Aqui também está outra solução pequena itertools.count()
(que é praticamente a mesma abordagem que enumerar):
from itertools import izip as zip, count # izip for maximum efficiency
[i for i, j in zip(count(), ['foo', 'bar', 'baz']) if j == 'bar']
Isso é 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()
retorna o primeiro índice de valor!
| índice (...)
| L.index (valor, [iniciar, [parar]]) -> inteiro - retorna o primeiro índice do 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"])
Surgirá um problema se o elemento não estiver na lista. Esta função lida com o 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']
Você precisa definir uma condição para verificar se o elemento que você está pesquisando está na lista
if 'your_element' in mylist:
print mylist.index('your_element')
else:
print None
Todas as funções propostas aqui reproduzem o comportamento inerente da linguagem, mas obscurecem o que está acontecendo.
[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 manipulação de exceção se a linguagem fornece os métodos para fazer o que você deseja?
Se você deseja todos os índices, pode usar o 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 clara e legível.
Localizando o índice de um item, dada uma lista que o contém em Python
Para uma lista
["foo", "bar", "baz"]
e um item da lista"bar"
, qual é a maneira mais limpa de obter seu índice (1) no Python?
Bem, claro, existe o método index, que retorna o índice da primeira ocorrência:
>>> l = ["foo", "bar", "baz"]
>>> l.index('bar')
1
Existem alguns problemas com este método:
ValueError
Se o valor estiver faltando, você precisará capturar o ValueError
.
Você pode fazer isso com uma definição reutilizável como esta:
def index(a_list, value):
try:
return a_list.index(value)
except ValueError:
return None
E use-o assim:
>>> print(index(l, 'quux'))
None
>>> print(index(l, 'bar'))
1
E a desvantagem disso é que você provavelmente verificará se o valor retornado is
ou is not
Nenhum:
result = index(a_list, value)
if result is not None:
do_something(result)
Se você puder ter mais ocorrências, não obterá informações completas com list.index
:
>>> l.append('bar')
>>> l
['foo', 'bar', 'baz', 'bar']
>>> l.index('bar') # nothing at index 3?
1
Você pode enumerar em uma 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 você não tiver ocorrências, poderá verificar isso com verificação booleana do resultado ou simplesmente não fazer nada se fizer um loop sobre os resultados:
indexes = [index for index, v in enumerate(l) if v == 'boink']
for index in indexes:
do_something(index)
Se você tem pandas, pode facilmente obter essas informações com um objeto Series:
>>> import pandas as pd
>>> series = pd.Series(l)
>>> series
0 foo
1 bar
2 baz
3 bar
dtype: object
Uma verificação de comparação retornará uma série de booleanos:
>>> series == 'bar'
0 False
1 True
2 False
3 True
dtype: bool
Passe essa série de booleanos para a série por meio de notação subscrita e você obterá apenas os membros correspondentes:
>>> series[series == 'bar']
1 bar
3 bar
dtype: object
Se você deseja apenas os índices, o atributo index retorna uma série de números inteiros:
>>> series[series == 'bar'].index
Int64Index([1, 3], dtype='int64')
E se você os quiser em uma lista ou tupla, apenas passe-os para o construtor:
>>> list(series[series == 'bar'].index)
[1, 3]
Sim, você também pode usar uma compreensão de lista com enumerar, mas isso não é tão elegante, na minha opinião - você está fazendo testes de igualdade em Python, em vez de permitir que o código interno escrito em C lide com isso:
>>> [i for i, value in enumerate(l) if value == 'bar']
[1, 3]
O problema XY é perguntar sobre sua tentativa de solução, e não sobre o seu problema real.
Por que você acha que precisa do índice com um elemento em uma lista?
Se você já conhece o valor, por que se importa onde ele está em uma lista?
Se o valor não estiver lá, pegar o ValueError
é bastante detalhado - e prefiro evitar isso.
De qualquer maneira, eu estou repetindo a lista de qualquer maneira, por isso usualmente apontarei para qualquer informação interessante, obtendo o índice com enumerate.
Se você estiver pesquisando dados, provavelmente deve usar pandas - que tem ferramentas muito mais elegantes do que as soluções puras de Python que mostrei.
Não me lembro de precisar list.index
, eu mesmo. No entanto, examinei a biblioteca padrão do Python e vejo alguns usos excelentes para ela.
Existem muitos, muitos usos para isso idlelib
, na GUI e na análise de texto.
o keyword
módulo o utiliza para encontrar marcadores de comentários no módulo para regenerar automaticamente a lista de palavras-chave nele por metaprogramação.
No Lib / mailbox.py, parece 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
No Lib / tarfile.py, semelhante ao distutils, para obter uma fatia de um item:
members = members[:members.index(tarinfo)]
Em Lib / pickletools.py:
numtopop = before.index(markobject)
O que esses usos parecem ter em comum é que eles parecem operar em listas de tamanhos restritos (importante por causa do tempo de pesquisa de O (n) list.index
) e são usados principalmente na análise (e na interface do usuário no caso de inatividade).
Embora existam casos de uso para isso, eles são bastante incomuns. Se você encontrar essa resposta, pergunte-se se o que está fazendo é o uso mais direto das ferramentas fornecidas pelo idioma para o seu caso de uso.
Todos os índices com a 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')
Com enumerate (alist), 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]
>>>
Essa função pega o item e a lista como argumentos e retorna a posição do item na lista, como vimos anteriormente.
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"))
Resultado
[1, 3, 5, 7]
for n, i in enumerate([1, 2, 3, 4, 1]):
if i == 1:
print(n)
Resultado:
0
4
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]
>>>
... como confirmar a existência do item antes de obter o índice. O bom dessa abordagem é que a função sempre retorna uma lista de índices - mesmo que seja uma lista vazia. Também funciona com strings.
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 em uma janela python interativa:
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]
>>>
Depois de mais um ano de desenvolvimento python, estou um pouco envergonhado com a minha resposta original; portanto, para esclarecer as coisas, certamente é possível usar o código acima; no entanto, a maneira muito mais idiomática de obter o mesmo comportamento seria usar a compreensão da lista, junto com a função enumerate ().
Algo assim:
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')
Que, quando colado em uma janela python interativa, gera:
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 revisar esta pergunta e todas as respostas, percebo que é exatamente isso que o FMc sugeriu em sua resposta anterior . No momento em que originalmente respondi a essa pergunta, eu nem vi , porque não a entendi. Espero que meu exemplo um pouco mais detalhado ajude a entender.
Se a única linha de código acima ainda não faz sentido para você, recomendo que você compreenda a lista de python do Google e reserve alguns minutos para se familiarizar. É apenas um dos muitos recursos poderosos que tornam uma alegria usar o Python para desenvolver código.
Uma variante na resposta do FMc e user7177 fornecerá um ditado que pode retornar 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]}
>>>
Você também pode usar isso como uma linha para obter todos os índices para uma única entrada. Não há garantias de eficiência, embora eu tenha usado o conjunto (a) para reduzir o número de vezes que o lambda é chamado.
Localizando o índice do item x na lista L:
idx = L.index(x) if (x in L) else -1
Como as listas Python são baseadas em zero, podemos usar a função interna zip da seguinte maneira:
>>> [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 ser procurado.
(Observação: aqui estamos iterando usando i para obter os índices, mas se precisarmos nos concentrar nos itens, podemos mudar para 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)
Isso explica se a string também não está na lista, se não estiver na lista, location = -1
O index()
método Python gera um erro se o item não foi encontrado. Portanto, você pode torná-lo semelhante à indexOf()
função do JavaScript, que retorna -1
se o item não foi encontrado:
try:
index = array.index('search_keyword')
except ValueError:
index = -1
Há uma resposta mais funcional para isso.
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))))))
Scala
/ funcionais de programação entusiastas
Vamos dar o nome lst
à lista que você possui. Pode-se converter a lista lst
para a numpy array
. E, em seguida, use numpy.where para obter o índice do item escolhido na lista. A seguir está a maneira pela qual você o implementará.
import numpy as np
lst = ["foo", "bar", "baz"] #lst: : 'list' data type
print np.where( np.array(lst) == 'bar')[0][0]
>>> 1
Para quem vem de outro idioma como eu, talvez com um loop simples seja mais fácil entender e usá-lo:
mylist = ["foo", "bar", "baz", "bar"]
newlist = enumerate(mylist)
for index, item in newlist:
if item == "bar":
print(index, item)
Sou grato por Então, o que exatamente enumerar faz? . Isso me ajudou a entender.
Se você vai encontrar um índice uma vez, então o método "index" é bom. No entanto, se você deseja pesquisar seus dados mais de uma vez, recomendo o uso do módulo bisect . Lembre-se de que os dados do módulo bisect devem ser classificados. Assim, você classifica os dados uma vez e depois pode usar a divisão. O uso do módulo bisect na minha máquina é cerca de 20 vezes mais rápido do que o método index.
Aqui está um exemplo de código usando a sintaxe Python 3.8 e acima:
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}")
Resultado:
t1=0.0400, t2=0.0020, diffs t1/t2=19.60
É mencionado em numerosas respostas que o método incorporado de list.index(item)
método é um algoritmo O (n). Tudo bem se você precisar fazer isso uma vez. Mas se você precisar acessar os índices dos elementos várias vezes, faz mais sentido criar primeiro um dicionário (O (n)) de pares de índice de itens e, em seguida, acessar o índice em O (1) toda vez que precisar isto.
Se você tiver certeza de que os itens da sua lista nunca serão repetidos, poderá 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 você pode ter elementos duplicados e precisar retornar 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]
Conforme indicado por @TerryA, muitas respostas discutem como encontrar um índice.
more_itertools
é uma biblioteca de terceiros com ferramentas para localizar vários índices em um iterável.
Dado
import more_itertools as mit
iterable = ["foo", "bar", "baz", "ham", "foo", "bar", "baz"]
Código
Encontre índices de múltiplas observações:
list(mit.locate(iterable, lambda x: x == "bar"))
# [1, 5]
Teste 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
. Instale via > pip install more_itertools
.
usando o dicionário, onde processa a lista primeiro e depois adiciona o índice a ela
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]
na minha opinião o ["foo", "bar", "baz"].index("bar")
é bom, mas não é suficiente! porque se "bar" não estiver no dicionário, ValueError
elevado . Então você pode usar esta função:
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 o resultado é:
1
e se o nome não estava em arr, a função retornará -1. por exemplo:
print (find_index (["foo", "bar", "baz"], "fooo"))
-1
l = [1, 2]; find_index(l, 3)
retornaria -1
e l[find_index(l, 3)]
retornaria 2
. -1 é uma coisa ruim para retornar, basta retornar None.
"bar"
, [2] Todos os índices de"bar"
?