Quel est le moyen le plus rapide de savoir si une valeur existe dans une liste (une liste contenant des millions de valeurs) et quel est son index?
Je sais que toutes les valeurs de la liste sont uniques comme dans cet exemple.
La première méthode que j'essaie est (3,8 secondes dans mon vrai code):
a = [4,2,3,1,5,6]
if a.count(7) == 1:
b=a.index(7)
"Do something with variable b"
La deuxième méthode que j'essaie est (2x plus rapide: 1,9 sec pour mon vrai code):
a = [4,2,3,1,5,6]
try:
b=a.index(7)
except ValueError:
"Do nothing"
else:
"Do something with variable b"
Méthodes proposées par l'utilisateur Stack Overflow (2,74 s pour mon vrai code):
a = [4,2,3,1,5,6]
if 7 in a:
a.index(7)
Dans mon code réel, la première méthode prend 3,81 secondes et la seconde méthode prend 1,88 secondes. C'est une bonne amélioration, mais:
Je suis un débutant en Python / scripting, et existe-t-il un moyen plus rapide de faire les mêmes choses et d'économiser plus de temps de traitement?
Explication plus spécifique pour mon application:
Dans l'API Blender, je peux accéder à une liste de particules:
particles = [1, 2, 3, 4, etc.]
De là, je peux accéder à l'emplacement d'une particule:
particles[x].location = [x,y,z]
Et pour chaque particule, je teste si un voisin existe en recherchant chaque emplacement de particule comme ceci:
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])
la source
bisect
moduleRéponses:
Le moyen le plus clair et le plus rapide de le faire.
Vous pouvez également envisager d'utiliser un
set
, mais la construction de cet ensemble à partir de votre liste peut prendre plus de temps que les tests d'adhésion plus rapides vous feront gagner. La seule façon d'en être certain est de bien se comparer. (cela dépend également des opérations dont vous avez besoin)la source
Comme indiqué par d'autres,
in
peut être très lent pour les grandes listes. Voici quelques comparaisons des performances pourin
,set
etbisect
. Notez que le temps (en secondes) est en échelle logarithmique.Code de test:
la source
import random / import bisect / import matplotlib.pyplot as plt
puis appelez:profile()
range()
objet. Lors de l'utilisationvar in [integer list]
, voyez si unrange()
objet peut modéliser la même séquence. Très proche en performance d'un set, mais plus concis.Vous pouvez mettre vos articles dans un fichier
set
. Les recherches d'ensemble sont très efficaces.Essayer:
modifier Dans un commentaire, vous dites que vous souhaitez obtenir l'index de l'élément. Malheureusement, les ensembles n'ont aucune notion de position des éléments. Une alternative consiste à pré-trier votre liste, puis à utiliser la recherche binaire chaque fois que vous avez besoin de trouver un élément.
la source
Usage
Je crois que c'est le moyen le plus rapide de savoir si une valeur choisie est dans un tableau.
la source
return 'a' in a
?o='--skip'; o in ("--skip-ias"); # returns True !
in
opérateur fonctionne de la même manière pour tester l'appartenance à la sous-chaîne. La partie déroutante ici est probablement que ce("hello")
n'est pas un tuple à valeur unique, alors que("hello",)
c'est - la virgule fait la différence.o in ("--skip-ias",)
estFalse
comme prévu.Ce ne sera une bonne idée que si a ne change pas et nous pouvons donc faire la partie dict () une fois, puis l'utiliser à plusieurs reprises. Si cela change, veuillez fournir plus de détails sur ce que vous faites.
la source
La question initiale était:
Il y a donc deux choses à trouver:
Pour cela, j'ai modifié le code @xslittlegrass pour calculer les index dans tous les cas et ajouté une méthode supplémentaire.
Résultats
Les méthodes sont:
Les résultats montrent que la méthode 5 est la plus rapide.
Fait intéressant, les méthodes try et set sont équivalentes dans le temps.
Code de test
la source
Il semble que votre application puisse tirer avantage de l'utilisation d'une structure de données Bloom Filter.
En bref, une recherche de filtre de bloom peut vous dire très rapidement si une valeur n'est DEFINITIVEMENT PAS présente dans un ensemble. Sinon, vous pouvez effectuer une recherche plus lente pour obtenir l'index d'une valeur QUI POURRAIT ÊTRE POSSIBLE dans la liste. Donc, si votre application a tendance à obtenir le résultat "non trouvé" beaucoup plus souvent que le résultat "trouvé", vous pouvez voir une accélération en ajoutant un filtre Bloom.
Pour plus de détails, Wikipedia fournit un bon aperçu du fonctionnement des filtres Bloom, et une recherche sur le Web pour "bibliothèque de filtres Bloom Python" fournira au moins quelques implémentations utiles.
la source
Sachez que l'
in
opérateur teste non seulement l'égalité (==
) mais aussi l'identité (is
), lain
logique delist
s est à peu près équivalente à la suivante (elle est en fait écrite en C et non en Python cependant, au moins en CPython):Dans la plupart des cas, ce détail n'est pas pertinent, mais dans certaines circonstances, il peut surprendre un novice Python, par exemple, qui
numpy.NAN
a la propriété inhabituelle de ne pas être égal à lui - même :Pour distinguer ces cas inhabituels, vous pouvez utiliser
any()
comme:Noter la
in
logique delist
s avecany()
serait:Cependant, je dois souligner qu'il s'agit d'un cas de bord, et pour la grande majorité des cas, l'
in
opérateur est hautement optimisé et exactement ce que vous voulez bien sûr (aveclist
ou avec unset
).la source
Ou utilisez
__contains__
:Démo:
la source
La solution de @Winston Ewert donne une grande accélération pour les très grandes listes, mais cette réponse de stackoverflow indique que la construction try: / except: / else: sera ralentie si la branche except est souvent atteinte. Une alternative est de profiter de la
.get()
méthode de dictée:La
.get(key, default)
méthode est juste pour le cas où vous ne pouvez pas garantir qu'une clé sera dans le dict. Si la clé est présente, elle renvoie la valeur (comme le feraitdict[key]
), mais lorsqu'elle ne l'est pas,.get()
renvoie votre valeur par défaut (iciNone
). Vous devez vous assurer dans ce cas que la valeur par défaut choisie ne sera pasa
.la source
Ce n'est pas le code, mais l'algorithme pour une recherche très rapide.
Si votre liste et la valeur que vous recherchez sont tous des nombres, c'est assez simple. Si cordes: regardez en bas:
Si vous avez également besoin de la position d'origine de votre numéro, recherchez-la dans la deuxième colonne d'index.
Si votre liste n'est pas composée de nombres, la méthode fonctionne toujours et sera la plus rapide, mais vous devrez peut-être définir une fonction qui pourra comparer / ordonner les chaînes.
Bien sûr, cela nécessite l'investissement de la méthode sorted (), mais si vous continuez à réutiliser la même liste pour la vérification, cela peut valoir la peine.
la source
Parce que la question n'est pas toujours censée être comprise comme le moyen technique le plus rapide - je suggère toujours le moyen le plus simple et le plus rapide pour comprendre / écrire: une compréhension de liste, une ligne
J'ai eu un
list_to_search_in
avec tous les éléments, et je voulais retourner les index des éléments dans lelist_from_which_to_search
.Cela renvoie les index dans une belle liste.
Il existe d'autres façons de vérifier ce problème - cependant, la compréhension des listes est assez rapide, ajoutant au fait de l'écrire assez rapidement, pour résoudre un problème.
la source
Pour moi, c'était 0,030 s (réel), 0,026 s (utilisateur) et 0,004 s (sys).
la source
Code pour vérifier si deux éléments existent dans un tableau dont le produit est égal à k:
la source