Qual é a maneira mais rápida de saber se existe um valor em uma lista (uma lista com milhões de valores) e qual é o seu índice?
Eu sei que todos os valores na lista são únicos, como neste exemplo.
O primeiro método que eu tento é (3,8 segundos no meu código real):
a = [4,2,3,1,5,6]
if a.count(7) == 1:
b=a.index(7)
"Do something with variable b"
O segundo método que eu tento é (2x mais rápido: 1,9 segundos para o meu código real):
a = [4,2,3,1,5,6]
try:
b=a.index(7)
except ValueError:
"Do nothing"
else:
"Do something with variable b"
Métodos propostos pelo usuário do Stack Overflow (2,74 s para o meu código real):
a = [4,2,3,1,5,6]
if 7 in a:
a.index(7)
No meu código real, o primeiro método leva 3,81 segundos e o segundo método 1,88 segundos. É uma boa melhoria, mas:
Sou iniciante em Python / script e existe uma maneira mais rápida de fazer as mesmas coisas e economizar mais tempo de processamento?
Explicações mais específicas para minha aplicação:
Na API do Blender, posso acessar uma lista de partículas:
particles = [1, 2, 3, 4, etc.]
De lá, eu posso acessar a localização de uma partícula:
particles[x].location = [x,y,z]
E para cada partícula, testo se existe um vizinho pesquisando cada local da partícula da seguinte maneira:
if [x+1,y,z] in particles.location
"Find the identity of this neighbour particle in x:the particle's index
in the array"
particles.index([x+1,y,z])
fonte
bisect
móduloRespostas:
A maneira mais clara e rápida de fazer isso.
Você também pode considerar usar a
set
, mas a construção desse conjunto a partir da sua lista pode levar mais tempo do que o teste mais rápido da associação economizará. A única maneira de ter certeza é avaliar bem. (isso também depende de quais operações você precisa)fonte
Conforme declarado por outros,
in
pode ser muito lento para listas grandes. Aqui estão algumas comparações das performances dein
,set
ebisect
. Observe que o tempo (em segundo) está na escala do log.Código para teste:
fonte
import random / import bisect / import matplotlib.pyplot as plt
e ligue para:profile()
range()
objeto humilde . Ao usarvar in [integer list]
, veja se umrange()
objeto pode modelar a mesma sequência. Muito próximo do desempenho de um conjunto, mas mais conciso.Você pode colocar seus itens em um
set
. As pesquisas de conjuntos são muito eficientes.Tentar:
editar Em um comentário, você diz que deseja obter o índice do elemento. Infelizmente, os conjuntos não têm noção de posição do elemento. Uma alternativa é pré-classificar sua lista e usar a pesquisa binária toda vez que você precisar encontrar um elemento.
fonte
Uso
Eu acredito que esta é a maneira mais rápida de saber se um valor escolhido está em uma matriz.
fonte
return 'a' in a
?o='--skip'; o in ("--skip-ias"); # returns True !
in
operador trabalha da mesma maneira para testar a associação de substring. A parte confusa aqui é provavelmente que("hello")
não é uma tupla de valor único, enquanto("hello",)
é - a vírgula faz a diferença.o in ("--skip-ias",)
éFalse
como esperado.Isso só será uma boa idéia se a não mudar e, portanto, podemos executar a parte dict () uma vez e usá-la repetidamente. Se um mudar, forneça mais detalhes sobre o que você está fazendo.
fonte
A pergunta original era:
Portanto, há duas coisas a encontrar:
Para isso, modifiquei o código @xslittlegrass para calcular índices em todos os casos e adicionei um método adicional.
Resultados
Os métodos são:
Os resultados mostram que o método 5 é o mais rápido.
Curiosamente, os métodos try e set são equivalentes no tempo.
Código de teste
fonte
Parece que seu aplicativo pode obter vantagens com o uso de uma estrutura de dados do Bloom Filter.
Em resumo, uma consulta ao filtro de bloom pode informar rapidamente se um valor NÃO está DEFINITIVAMENTE presente em um conjunto. Caso contrário, você pode fazer uma pesquisa mais lenta para obter o índice de um valor que POSSÍVEL PODE ESTAR na lista. Portanto, se seu aplicativo tende a obter o resultado "não encontrado" com muito mais frequência do que o resultado "encontrado", é possível acelerar a velocidade adicionando um filtro Bloom.
Para obter detalhes, a Wikipedia fornece uma boa visão geral de como os Filtros Bloom funcionam, e uma pesquisa na Web por "biblioteca de filtros python bloom" fornecerá pelo menos algumas implementações úteis.
fonte
Esteja ciente de que o
in
operador testa não apenas igualdade (==
), mas também identidade (is
), ain
lógica paralist
s é aproximadamente equivalente à seguinte (na verdade, é escrita em C e não em Python, pelo menos em CPython):Na maioria das circunstâncias, esse detalhe é irrelevante, mas em algumas circunstâncias ele pode surpreender um novato em Python, por exemplo,
numpy.NAN
tem a propriedade incomum de não ser igual a si mesmo :Para distinguir entre esses casos incomuns, você pode usar
any()
como:Observe que a
in
lógica paralist
s comany()
seria:No entanto, devo enfatizar que este é um caso extremo e, para a grande maioria dos casos, o
in
operador é altamente otimizado e exatamente o que você deseja, é claro (com umlist
ou com umset
).fonte
Ou use
__contains__
:Demo:
fonte
A solução do @Winston Ewert gera uma grande aceleração para listas muito grandes, mas essa resposta do stackoverflow indica que a construção try: / except: / else: será mais lenta se a ramificação de exceção for frequentemente alcançada. Uma alternativa é tirar proveito do
.get()
método para o ditado:O
.get(key, default)
método é apenas para o caso em que você não pode garantir que uma chave esteja no ditado. Se a chave estiver presente, ela retornará o valor (como seriadict[key]
), mas, quando não estiver,.get()
retornará o valor padrão (aquiNone
). Nesse caso, é necessário garantir que o padrão escolhido não estejaa
.fonte
Este não é o código, mas o algoritmo para pesquisas muito rápidas.
Se sua lista e o valor que você procura são todos números, isso é bastante direto. Se strings: olhe para o fundo:
Se você também precisar da posição original do seu número, procure-o na segunda coluna do índice.
Se sua lista não for feita de números, o método ainda funcionará e será mais rápido, mas pode ser necessário definir uma função que possa comparar / ordenar seqüências de caracteres.
Obviamente, isso precisa do investimento do método classificado (), mas se você continuar reutilizando a mesma lista para verificação, pode valer a pena.
fonte
Como a pergunta nem sempre deve ser entendida como a maneira técnica mais rápida - eu sempre sugiro a maneira mais direta e rápida de entender / escrever: uma lista de compreensão, uma linha
Eu tinha um
list_to_search_in
com todos os itens e queria retornar os índices dos itens nolist_from_which_to_search
.Isso retorna os índices em uma boa lista.
Existem outras maneiras de verificar esse problema - no entanto, as compreensões da lista são rápidas o suficiente, aumentando o fato de escrevê-lo rápido o suficiente para resolver um problema.
fonte
Para mim, foram 0,030 seg (real), 0,026 seg (usuário) e 0,004 seg (sys).
fonte
Código para verificar se existem dois elementos na matriz cujo produto é igual a k:
fonte