Als neue Testreihe zeigt @ EriF89 nach all den Jahren immer noch:
$ 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
Hier vergleichen wir auch a tuple
, von denen bekannt ist, dass sie lists
in einigen Anwendungsfällen schneller als (und weniger Speicher) sind. Im Falle der Nachschlagetabelle ist die tuple
Verkleidung nicht besser.
Sowohl die dict
als set
auch sehr gut. Dies wirft einen interessanten Punkt auf, der mit der @ SilentGhost-Antwort zur Eindeutigkeit zusammenhängt: Wenn das OP 10 Millionen Werte in einem Datensatz enthält und nicht bekannt ist, ob Duplikate darin enthalten sind, lohnt es sich, einen Satz / ein Diktat seiner Elemente parallel zu halten mit dem tatsächlichen Datensatz und Testen auf Existenz in diesem Satz / Diktat. Es ist möglich, dass die 10 Millionen Datenpunkte nur 10 eindeutige Werte haben, was einen viel kleineren Platz zum Suchen darstellt!
Der Fehler von SilentGhost in Bezug auf Diktate ist tatsächlich aufschlussreich, da man ein Diktat verwenden könnte, um doppelte Daten (in Werten) zu einem nicht duplizierten Satz (Schlüssel) zu korrelieren und somit ein Datenobjekt zu behalten, um alle Daten zu speichern, und dennoch schnell als Nachschlagetabelle zu sein. Ein Diktatschlüssel könnte beispielsweise der Wert sein, nach dem gesucht wird, und der Wert könnte eine Liste von Indizes in einer imaginären Liste sein, in der dieser Wert aufgetreten ist.
Wenn beispielsweise die zu durchsuchende Quelldatenliste war l=[1,2,3,1,2,1,4]
, könnte sie sowohl für die Suche als auch für den Speicher optimiert werden, indem sie durch dieses Diktat ersetzt wird:
>>> 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]})
Mit diesem Diktat kann man wissen:
- Wenn sich ein Wert im Originaldatensatz befand (dh
2 in d
zurückgegeben wird True
)
- Wo der Wert in dem ursprünglichen Datensatz war (dh
d[2]
zurückgibt Liste des Indizes , wo Daten wurden in Originaldatenliste gefunden: [1, 4]
)