作为一组新的测试表明@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 关于唯一性的答案相关:如果 OP 在数据集中有 10M 值,并且不知道其中是否存在重复项,那么值得保持其元素的集合/字典并行使用实际数据集,并测试该集/字典中的存在。 10M 数据点可能只有 10 个唯一值,这是一个更小的搜索空间!
SilentGhost 关于 dicts 的错误实际上是有启发性的,因为可以使用 dict 将重复数据(值中)关联到非重复集(键)中,从而保留一个数据对象来保存所有数据,但仍然可以快速查找桌子。例如,一个 dict 键可以是要查找的值,而该值可以是该值出现的虚构列表中的索引列表。
例如,如果要搜索的源数据列表是l=[1,2,3,1,2,1,4],则可以通过将其替换为以下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]})
有了这个字典,可以知道:
-
如果一个值在原始数据集中(即
2 in d 返回True)
-
在哪里该值在原始数据集中(即
d[2] 返回在原始数据列表中找到数据的索引列表:[1, 4])