web-dev-qa-db-ja.com

pythonでリストを検索する最速の方法

_"test" in a_のようなものを実行すると、aはリストですpythonリストで順次検索を実行するか、またはルックアップを最適化するためにハッシュテーブル表現を作成しますアプリケーションでこれが必要なのは、リストで多くのルックアップを実行するため、b = set(a)を実行してから_"test" in b_を実行するのが最善でしょうか?また、リストが値が重複することはなく、実際にはその順序を気にしません。値の存在を確認できるようにする必要があるだけです。

27
Ian Burris

また、取得する値のリストには重複するデータはなく、実際にはその順序は関係ありません。値の存在を確認できる必要があるだけです。

リストを使用せず、代わりに set() を使用してください。非常に高速なinテストを含む、まさに必要なプロパティがあります。

セットの1つのリストが変更された場所(ほとんどの場合、大量の処理)で20倍以上の高速化が見られました。

55
orlp

"test" in aリスト付きaは線形検索を行います。ハッシュテーブルをその場で設定すると、線形検索よりもはるかにコストがかかります。 "test" in bは、一方で、O(1)ハッシュルックアップを行います。

あなたが説明する場合、セットでリストを使用する理由はないようです。

8
Sven Marnach

セット実装で行くほうがいいと思います。セットにはO(1)ルックアップ時間があることを知っています。リストにはO(n)ルックアップ時間がかかると思います。ただし、リストがO(1)ルックアップ、セットに切り替えても何も失われません。

さらに、セットは重複する値を許可しません。これにより、プログラムのメモリ効率も若干向上します

1
inspectorG4dget

リストとタプルは同じ時間を持っているようで、 "in"の使用は大きなデータに対して遅いです:

>>> t = list(range(0, 1000000))
>>> a=time.time();x = [b in t for b in range(100234,101234)];print(time.time()-a)
1.66235494614
>>> t = Tuple(range(0, 1000000))
>>> a=time.time();x = [b in t for b in range(100234,101234)];print(time.time()-a)
1.6594209671

これははるかに良い解決策です: 巨大なリスト(python)での検索/検索の最も効率的な方法

それは超高速です:

>>> from bisect import bisect_left
>>> t = list(range(0, 1000000))
>>> a=time.time();x = [t[bisect_left(t,b)]==b for b in range(100234,101234)];print(time.time()-a)
0.0054759979248
0