¿Cuál es la forma más rápida de saber si existe un valor en una lista (una lista con millones de valores) y cuál es su índice?
Sé que todos los valores en la lista son únicos como en este ejemplo.
El primer método que intento es (3.8 segundos en mi código real):
a = [4,2,3,1,5,6]
if a.count(7) == 1:
b=a.index(7)
"Do something with variable b"
El segundo método que intento es (2 veces más rápido: 1.9 segundos para mi 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 propuestos del usuario de Stack Overflow (2.74 segundos para mi código real):
a = [4,2,3,1,5,6]
if 7 in a:
a.index(7)
En mi código real, el primer método tarda 3.81 segundos y el segundo método lleva 1.88 segundos. Es una buena mejora, pero:
Soy un principiante con Python / scripting, y ¿hay una manera más rápida de hacer lo mismo y ahorrar más tiempo de procesamiento?
Explicación más específica para mi aplicación:
En la API de Blender puedo acceder a una lista de partículas:
particles = [1, 2, 3, 4, etc.]
Desde allí, puedo acceder a la ubicación de una partícula:
particles[x].location = [x,y,z]
Y para cada partícula pruebo si existe un vecino buscando cada ubicación de la partícula de esta manera:
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])
fuente
bisect
móduloRespuestas:
La forma más clara y rápida de hacerlo.
También puede considerar usar un
set
, pero construir ese conjunto de su lista puede llevar más tiempo del que ahorrará la prueba de membresía más rápida. La única forma de estar seguro es comparar bien. (esto también depende de las operaciones que requiera)fuente
Como lo han dicho otros,
in
puede ser muy lento para listas grandes. Aquí hay algunas comparaciones de las actuaciones parain
,set
ybisect
. Tenga en cuenta que el tiempo (en segundos) está en escala logarítmica.Código para pruebas:
fuente
import random / import bisect / import matplotlib.pyplot as plt
y luego llame:profile()
range()
objeto. Cuando lo usevar in [integer list]
, vea si unrange()
objeto puede modelar la misma secuencia. Muy cercano en rendimiento a un conjunto, pero más conciso.Podrías poner tus artículos en un
set
. Las búsquedas de conjuntos son muy eficientes.Tratar:
editar En un comentario, dice que desea obtener el índice del elemento. Desafortunadamente, los conjuntos no tienen noción de posición del elemento. Una alternativa es ordenar previamente su lista y luego usar la búsqueda binaria cada vez que necesite encontrar un elemento.
fuente
Uso
Creo que esta es la forma más rápida de saber si un valor elegido está en una matriz.
fuente
return 'a' in a
?o='--skip'; o in ("--skip-ias"); # returns True !
in
operador funciona de la misma manera para probar la membresía de la subcadena. La parte confusa aquí es probablemente que("hello")
no es una tupla de valor único, mientras("hello",)
que la coma hace la diferencia.o in ("--skip-ias",)
esFalse
como se esperabaEsto solo será una buena idea si a no cambia y, por lo tanto, podemos hacer la parte dict () una vez y luego usarla repetidamente. Si un cambio cambia, proporcione más detalles sobre lo que está haciendo.
fuente
La pregunta original fue:
Por lo tanto, hay dos cosas para encontrar:
Hacia esto, modifiqué el código @xslittlegrass para calcular índices en todos los casos, y agregué un método adicional.
Resultados
Los métodos son:
Los resultados muestran que el método 5 es el más rápido.
Curiosamente, los métodos try y set son equivalentes en el tiempo.
Código de prueba
fuente
Parece que su aplicación podría obtener ventajas del uso de una estructura de datos de Bloom Filter.
En resumen, una búsqueda de filtro de floración puede decirle muy rápidamente si un valor NO ESTÁ DEFINITIVAMENTE presente en un conjunto. De lo contrario, puede realizar una búsqueda más lenta para obtener el índice de un valor que POSIBLEMENTE PUEDE SER en la lista. Entonces, si su aplicación tiende a obtener el resultado "no encontrado" con mucha más frecuencia que el resultado "encontrado", es posible que vea una mayor velocidad al agregar un filtro Bloom.
Para más detalles, Wikipedia proporciona una buena visión general de cómo funcionan los filtros Bloom, y una búsqueda en la web de "biblioteca de filtros de floración Python" proporcionará al menos un par de implementaciones útiles.
fuente
Tenga en cuenta que el
in
operador prueba no solo la igualdad (==
) sino también la identidad (is
), lain
lógica paralist
s es aproximadamente equivalente a la siguiente (aunque en realidad está escrita en C y no en Python, al menos en CPython):En la mayoría de las circunstancias, este detalle es irrelevante, pero en algunas circunstancias puede sorprender a un principiante de Python, por ejemplo,
numpy.NAN
tiene la propiedad inusual de no ser igual a sí mismo :Para distinguir entre estos casos inusuales, puede usar
any()
como:Tenga en cuenta que la
in
lógica paralist
s conany()
sería:Sin embargo, debo enfatizar que este es un caso extremo, y para la gran mayoría de los casos, el
in
operador está altamente optimizado y, por supuesto, exactamente lo que desea (ya sea conlist
o con aset
).fuente
O use
__contains__
:Manifestación:
fuente
La solución de @Winston Ewert produce una gran aceleración para listas muy grandes, pero esta respuesta de stackoverflow indica que la construcción try: / except: / else: se ralentizará si a menudo se alcanza la rama except. Una alternativa es aprovechar el
.get()
método para el dict:El
.get(key, default)
método es solo para el caso en el que no puede garantizar que una clave esté en el dict. Si la clave está presente, devuelve el valor (como lo haríadict[key]
), pero cuando no lo está,.get()
devuelve su valor predeterminado (aquíNone
). Debe asegurarse en este caso de que el valor predeterminado elegido no estará ena
.fuente
Este no es el código, sino el algoritmo para una búsqueda muy rápida.
Si su lista y el valor que está buscando son todos números, esto es bastante sencillo. Si las cadenas: mira en la parte inferior:
Si también necesita la posición original de su número, búsquela en la segunda columna de índice.
Si su lista no está compuesta de números, el método aún funciona y será más rápido, pero es posible que necesite definir una función que pueda comparar / ordenar cadenas.
Por supuesto, esto necesita la inversión del método sorted (), pero si sigue reutilizando la misma lista para verificar, puede valer la pena.
fuente
Debido a que no siempre se supone que la pregunta debe entenderse como la forma técnica más rápida, siempre sugiero la forma más directa y más rápida de entender / escribir: una lista de comprensión, una línea
Tuve un
list_to_search_in
con todos los elementos, y quería devolver los índices de los elementos en ellist_from_which_to_search
.Esto devuelve los índices en una buena lista.
Hay otras formas de verificar este problema; sin embargo, las comprensiones de listas son lo suficientemente rápidas, lo que se suma al hecho de escribirlo lo suficientemente rápido como para resolver un problema.
fuente
Para mí fue 0.030 segundos (real), 0.026 segundos (usuario) y 0.004 segundos (sys).
fuente
Código para verificar si existen dos elementos en la matriz cuyo producto es igual a k:
fuente