Như một bộ thử nghiệm mới để hiển thị @ EriF89 vẫn đúng sau tất cả những năm này:
$ 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
Ở đây chúng tôi cũng so sánh a tuple
, được biết là nhanh hơn lists
(và sử dụng ít bộ nhớ hơn) trong một số trường hợp sử dụng. Trong trường hợp bảng tra cứu, tuple
faired không tốt hơn.
Cả dict
và set
thực hiện rất tốt. Điều này mang đến một điểm thú vị khi đưa vào câu trả lời @SilentGhost về tính duy nhất: nếu OP có 10M giá trị trong một tập dữ liệu và không biết có trùng lặp trong đó hay không, thì sẽ đáng để giữ song song một tập hợp / các phần tử của nó với tập dữ liệu thực tế và kiểm tra sự tồn tại trong tập / dict đó. Có thể các điểm dữ liệu 10 triệu chỉ có 10 giá trị duy nhất, đó là một không gian nhỏ hơn nhiều để tìm kiếm!
Sai lầm của SilentGhost về các dicts thực sự đang phát sáng vì người ta có thể sử dụng một lệnh để tương quan dữ liệu trùng lặp (trong các giá trị) thành một tập hợp không trùng lặp (các khóa) và do đó giữ một đối tượng dữ liệu để giữ tất cả dữ liệu, nhưng vẫn nhanh như một bảng tra cứu. Ví dụ: khóa dict có thể là giá trị được tra cứu và giá trị có thể là danh sách các chỉ mục trong danh sách tưởng tượng nơi giá trị đó xảy ra.
Ví dụ: nếu danh sách dữ liệu nguồn cần tìm kiếm l=[1,2,3,1,2,1,4]
, nó có thể được tối ưu hóa cho cả tìm kiếm và bộ nhớ bằng cách thay thế nó bằng lệnh này:
>>> 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]})
Với chính tả này, người ta có thể biết:
- Nếu một giá trị nằm trong tập dữ liệu gốc (nghĩa là
2 in d
trả về True
)
- Trường hợp giá trị nằm trong tập dữ liệu gốc (nghĩa là
d[2]
trả về danh sách các chỉ mục nơi dữ liệu được tìm thấy trong danh sách dữ liệu gốc [1, 4]
:)