Як новий набір тестів, які показують @ EriF89, все ще вірно після всіх цих років:
$ 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
Тут ми також порівнюємо а tuple
, які, як відомо, є швидшими, ніж lists
(і використовують менше пам'яті) в деяких випадках використання. Що стосується таблиці пошуку, то tuple
слабкіше не краще.
І те, dict
і set
виконано дуже добре. Це викликає цікавий момент, пов’язаний з відповіддю @SilentGhost про унікальність: якщо ОП має 10M значень у наборі даних, і невідомо, чи є в них дублікати, то варто було б паралельно зберігати набір / диктування його елементів. з фактичним набором даних та тестуванням на наявність у цьому наборі / dict. Можливо, що в 10M точках даних є лише 10 унікальних значень, що є значно меншим простором для пошуку!
Помилка SilentGhost щодо диктів насправді висвітлює, тому що можна використовувати диктант для співвіднесення дублюваних даних (у значеннях) у недуплений набір (ключі) і, таким чином, зберігати один об’єкт даних, щоб зберігати всі дані, але все ще бути швидким як таблиця пошуку. Наприклад, ключем dict може бути значення, яке шукається, а значення може бути переліком індексів у уявному списку, де це значення відбулося.
Наприклад, якщо список вихідних даних, який слід шукати, був l=[1,2,3,1,2,1,4]
оптимізований як для пошуку, так і для пам'яті, замінивши його цим диктом:
>>> 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]})
З цього диктату можна знати:
- Якщо значення було в початковому наборі даних (тобто
2 in d
повернення True
)
- Якщо значення було у вихідному наборі даних (тобто
d[2]
повертає список індексів , де дані були знайдені в первинному списку даних: [1, 4]
)