@ 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個しかない可能性があります。これは、検索するスペースがはるかに小さいことを意味します。
dictを使用して重複したデータ(値)を重複していないセット(キー)に関連付け、1つのデータオブジェクトを保持してすべてのデータを保持しながら、ルックアップテーブルとして高速であるため、dictsに関する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]
)