Estou um pouco confuso com esta pergunta: você deseja procurar por um item recursivamente em todos os níveis de uma lista multidimensional ou apenas por ocorrências no nível superior da lista?
Anderson Green
22
Na minha opinião, deve haver um método de lista que faça exatamente isso.
Otocan
Respostas:
545
Você pode usar uma compreensão de lista:
indices =[i for i, x in enumerate(my_list)if x =="whatever"]
Nos pitões mais antigos, use filter () para essencialmente a mesma funcionalidade.
Gleno
44
As compreensões de lista apareceram em python em 2.0, enumerateem 2.3. Então, sim, se o seu Python é antigo, use filter().
Steven Rumbalski
2
Essa técnica não encontrará todas as ocorrências de um item em uma matriz multidimensional. Por exemplo, print([i for i, x in enumerate([[1,1],[0,1]]) if x == 1])retorna em []vez de [[0, 1], [0, 0], [1, 1]].
Anderson Green
10
@AndersonGreen: O termo "matriz multidimensional" sugere uma estrutura de dados que garante um tamanho uniforme ao longo de cada um de seus eixos. Não existe essa estrutura de dados no Python simples. Há listas de listas, mas elas são muito diferentes de "matrizes multidimensionais". Se você quiser o último, considere usar o NumPy, que permite fazer coisas como (a == 1).nonzero()para uma matriz NumPy a.
Sven Marnach 04/02
2
@ MadmanLee Se você quiser algo rápido, use NumPy. Veja a resposta de JoshAdel
Georgy
117
Embora não seja uma solução para listas diretamente, numpyrealmente brilha para esse tipo de coisa:
import numpy as np
values = np.array([1,2,3,1,2,4,5,6,3,2,1])
searchval =3
ii = np.where(values == searchval)[0]
retorna:
ii ==>array([2,8])
Isso pode ser significativamente mais rápido para listas (matrizes) com um grande número de elementos versus algumas das outras soluções.
Notei que o [0] no final converte o que seria uma matriz em uma string. Estou curioso por que você escolheu fazer isso.
Amelia
5
@amelia [0]é necessária porque whereretorna uma tupla(array([2, 8], dtype=int64),)
Winand
11
Hey, @Winand eu coloquei [0], mas ainda tenho as duas partes. Aqui está o meu código: (nrg.local_logs.all_id_resp_address é uma lista) "ste =" 199.38.164.165 "value = np.where (nrg.local_logs.all_id_resp_address == ste) [0]" Ficarei feliz se você puder dizer -me o que eu fiz de errado
Tomer
2
@ Antes de mais nada all_id_resp_address, np.arraynão deve ser list.
Winand
11
@ Você tentou comparar liste str, obviamente, passou Falsepara np.where. Quando você compara np.arraycom smth. você obtém uma matriz de valores booleanos. Em seguida, np.wherelocaliza as posições de todos os Truevalores dessa matriz.
Winand
29
Uma solução usando list.index:
def indices(lst, element):
result =[]
offset =-1whileTrue:try:
offset = lst.index(element, offset+1)exceptValueError:return result
result.append(offset)
É muito mais rápido do que a compreensão da lista enumerate, para listas grandes. Também é muito mais lento que a numpysolução, se você já possui a matriz, caso contrário, o custo da conversão supera o ganho de velocidade (testado em listas inteiras com 100, 1000 e 10000 elementos).
NOTA: Uma nota de cautela com base no comentário de Chris_Rands: esta solução é mais rápida que a compreensão da lista se os resultados forem suficientemente escassos, mas se a lista tiver muitas instâncias do elemento que está sendo pesquisado (mais de ~ 15% da lista , em um teste com uma lista de 1000 números inteiros), a compreensão da lista é mais rápida.
Você diz que isso é mais rápido que um comp de lista, pode mostrar seus horários que demonstram isso?
9789 Chris_Rands
5
Isso foi há muito tempo, eu provavelmente usei timeit.timeitcom listas geradas aleatoriamente. Esse é um ponto importante, e suponho que seja por isso que você pergunta. Na época, isso não me ocorreu, mas os ganhos de velocidade só são verdadeiros se os resultados forem suficientemente escassos. Acabei de testar com uma lista cheia do elemento a ser pesquisado e é muito mais lento que a compreensão da lista.
Paulo Almeida
18
E se:
In[1]: l=[1,2,3,4,3,2,5,6,7]In[2]:[i for i,val in enumerate(l)if val==3]Out[2]:[2,4]
Obtendo todas as ocorrências e a posição de um ou mais itens (idênticos) em uma lista
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]>>>
Vamos fazer nossa função findindex
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]
Simples
for n, i in enumerate([1,2,3,4,1]):if i ==1:print(n)
Essa resposta foi a mais fácil de implementar no meu código existente.
Ryan Harris
2
Usando um for-loop:
As respostas enumeratee a compreensão de uma lista são mais eficientes e pitônicas, no entanto, essa resposta é direcionada a estudantes que talvez não tenham permissão para usar algumas dessas funções internas .
crie uma lista vazia, indices
crie o loop com for i in range(len(x)): , que itera essencialmente através de uma lista de locais de índice[0, 1, 2, 3, ..., len(x)-1]
no loop, adicione qualquer i, onde x[i]é uma correspondência value, paraindices
def get_indices(x: list, value: int)-> list:
indices = list()for i in range(len(x)):if x[i]== value:
indices.append(i)return indices
n =[1,2,3,-50,-60,0,6,9,-60,-60]print(get_indices(n,-60))>>>[4,8,9]
As funções, get_indicessão implementadas com dicas de tipo . Nesse caso, a lista n,, é um monte de ints, portanto, procuramos por value, também definido como um int.
Usando a while-loope .index:
Com .index, use try-exceptpara tratamento de erros, pois ValueErrorocorrerá um se valuenão estiver na lista.
def get_indices(x: list, value: int)-> list:
indices = list()
i =0whileTrue:try:# find an occurrence of value and update i to that index
i = x.index(value, i)# add i to the list
indices.append(i)# advance i by 1
i +=1exceptValueErroras e:breakreturn indices
print(get_indices(n,-60))>>>[4,8,9]
Respostas:
Você pode usar uma compreensão de lista:
fonte
enumerate
em 2.3. Então, sim, se o seu Python é antigo, usefilter()
.print([i for i, x in enumerate([[1,1],[0,1]]) if x == 1])
retorna em[]
vez de[[0, 1], [0, 0], [1, 1]]
.(a == 1).nonzero()
para uma matriz NumPya
.Embora não seja uma solução para listas diretamente,
numpy
realmente brilha para esse tipo de coisa:retorna:
Isso pode ser significativamente mais rápido para listas (matrizes) com um grande número de elementos versus algumas das outras soluções.
fonte
[0]
é necessária porquewhere
retorna uma tupla(array([2, 8], dtype=int64),)
all_id_resp_address
,np.array
não deve serlist
.list
estr
, obviamente, passouFalse
paranp.where
. Quando você comparanp.array
com smth. você obtém uma matriz de valores booleanos. Em seguida,np.where
localiza as posições de todos osTrue
valores dessa matriz.Uma solução usando
list.index
:É muito mais rápido do que a compreensão da lista
enumerate
, para listas grandes. Também é muito mais lento que anumpy
solução, se você já possui a matriz, caso contrário, o custo da conversão supera o ganho de velocidade (testado em listas inteiras com 100, 1000 e 10000 elementos).NOTA: Uma nota de cautela com base no comentário de Chris_Rands: esta solução é mais rápida que a compreensão da lista se os resultados forem suficientemente escassos, mas se a lista tiver muitas instâncias do elemento que está sendo pesquisado (mais de ~ 15% da lista , em um teste com uma lista de 1000 números inteiros), a compreensão da lista é mais rápida.
fonte
timeit.timeit
com listas geradas aleatoriamente. Esse é um ponto importante, e suponho que seja por isso que você pergunta. Na época, isso não me ocorreu, mas os ganhos de velocidade só são verdadeiros se os resultados forem suficientemente escassos. Acabei de testar com uma lista cheia do elemento a ser pesquisado e é muito mais lento que a compreensão da lista.E se:
fonte
fonte
more_itertools.locate
localiza índices para todos os itens que satisfazem uma condição.more_itertools
é uma biblioteca de terceiros> pip install more_itertools
.fonte
conda install
se transformou muito instável no desempenho ultimamente)Mais uma solução (desculpe se duplicadas) para todas as ocorrências:
fonte
Ou use
range
(python 3):Para (python 2):
E então (ambos os casos):
É como esperado.
fonte
Usando filter () em python2.
fonte
Você pode criar um padrão
fonte
Obtendo todas as ocorrências e a posição de um ou mais itens (idênticos) em uma lista
Com enumerate (alist), você pode armazenar o primeiro elemento (n) que é o índice da lista quando o elemento x é igual ao que você procura.
Vamos fazer nossa função findindex
Essa função pega o item e a lista como argumentos e retorna a posição do item na lista, como vimos anteriormente.
Resultado
Simples
Resultado:
fonte
Usando um
for-loop
:enumerate
e a compreensão de uma lista são mais eficientes e pitônicas, no entanto, essa resposta é direcionada a estudantes que talvez não tenham permissão para usar algumas dessas funções internas .indices
for i in range(len(x)):
, que itera essencialmente através de uma lista de locais de índice[0, 1, 2, 3, ..., len(x)-1]
i
, ondex[i]
é uma correspondênciavalue
, paraindices
x[i]
acessa a lista por índiceget_indices
são implementadas com dicas de tipo . Nesse caso, a listan
,, é um monte deint
s, portanto, procuramos porvalue
, também definido como umint
.Usando a
while-loop
e.index
:.index
, usetry-except
para tratamento de erros, poisValueError
ocorrerá um sevalue
não estiver na lista.fonte
get_indeices
é um pouco mais rápida (~ 15%) do que a compreensão normal da lista. Eu estou tentando descobrir isso.Se você estiver usando o Python 2, poderá obter a mesma funcionalidade com isso:
Onde
my_list
está a lista da qual você deseja obter os índices evalue
o valor pesquisado. Uso:fonte
Se você precisar procurar todas as posições de elementos entre determinados índices , poderá indicá-los:
fonte