En tant que nouvel ensemble de tests à montrer, @ EriF89 a toujours raison après toutes ces années:
$ python -m timeit -s "l={k:k for k in xrange(5000)}" "[i for i in xrange(10000) if i in l]"
1000 loops, best of 3: 1.84 msec per loop
$ python -m timeit -s "l=[k for k in xrange(5000)]" "[i for i in xrange(10000) if i in l]"
10 loops, best of 3: 573 msec per loop
$ python -m timeit -s "l=tuple([k for k in xrange(5000)])" "[i for i in xrange(10000) if i in l]"
10 loops, best of 3: 587 msec per loop
$ python -m timeit -s "l=set([k for k in xrange(5000)])" "[i for i in xrange(10000) if i in l]"
1000 loops, best of 3: 1.88 msec per loop
Ici, nous comparons également a tuple
, qui sont connus pour être plus rapides que lists
(et utiliser moins de mémoire) dans certains cas d'utilisation. Dans le cas d'une table de consultation, le tuple
carénage n'est pas meilleur.
Le dict
etset
ont très bien performé. Cela soulève un point intéressant lié à la réponse @SilentGhost sur l'unicité: si l'OP a 10M de valeurs dans un ensemble de données, et qu'on ne sait pas s'il y a des doublons, alors il vaudrait la peine de garder un ensemble / dict de ses éléments en parallèle avec l'ensemble de données réel, et tester l'existence dans cet ensemble / dict. Il est possible que les 10 millions de points de données n'aient que 10 valeurs uniques, ce qui est un espace beaucoup plus petit pour la recherche!
L'erreur de SilentGhost à propos des dictionnaires est en fait éclairante car on pourrait utiliser un dict pour corréler des données dupliquées (en valeurs) dans un ensemble non dupliqué (clés), et ainsi conserver un objet de données pour contenir toutes les données, tout en restant rapide comme table de recherche. Par exemple, une clé dict pourrait être la valeur recherchée, et la valeur pourrait être une liste d'indices dans une liste imaginaire où cette valeur s'est produite.
Par exemple, si la liste de données source à rechercher était l=[1,2,3,1,2,1,4]
, elle pourrait être optimisée pour la recherche et la mémoire en la remplaçant par ce dict:
>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> l=[1,2,3,1,2,1,4]
>>> for i, e in enumerate(l):
... d[e].append(i)
>>> d
defaultdict(<class 'list'>, {1: [0, 3, 5], 2: [1, 4], 3: [2], 4: [6]})
Avec ce dict, on peut savoir:
- Si une valeur était dans l'ensemble de données d'origine (c.-à-d.
2 in d
Renvoie True
)
- Où la valeur était dans l'ensemble de données d' origine (c. -à-
d[2]
retourne la liste des indices où les données ont été énumérées dans la liste de données d' origine: [1, 4]
)