[英]How to efficiently check if an element is in a list of lists in python
[英]Python: how to check that if an item is in a list efficiently?
我有一個字符串列表(像這樣的單詞),當我解析文本時,我需要檢查一個單詞是否屬於我當前列表中的單詞組。
但是,我的輸入非常大(大約6億行),並且根據Python文檔檢查元素是否屬於列表是O(n)操作。
我的代碼是這樣的:
words_in_line = []
for word in line:
if word in my_list:
words_in_line.append(word)
由於花費了太多時間(實際上是幾天),我想改進大部分時間花費的那部分。 我看看Python集合,更准確地說,看看deque。 但是,只允許O(1)操作時間訪問列表的頭部和尾部,而不是在中間。
有人知道如何以更好的方式做到這一點嗎?
您可以考慮使用trie或DAWG或數據庫。 有幾個相同的Python實現。
以下是您考慮集合與列表的相關時間:
import timeit
import random
with open('/usr/share/dict/words','r') as di: # UNIX 250k unique word list
all_words_set={line.strip() for line in di}
all_words_list=list(all_words_set) # slightly faster if this list is sorted...
test_list=[random.choice(all_words_list) for i in range(10000)]
test_set=set(test_list)
def set_f():
count = 0
for word in test_set:
if word in all_words_set:
count+=1
return count
def list_f():
count = 0
for word in test_list:
if word in all_words_list:
count+=1
return count
def mix_f():
# use list for source, set for membership testing
count = 0
for word in test_list:
if word in all_words_set:
count+=1
return count
print "list:", timeit.Timer(list_f).timeit(1),"secs"
print "set:", timeit.Timer(set_f).timeit(1),"secs"
print "mixed:", timeit.Timer(mix_f).timeit(1),"secs"
打印:
list: 47.4126560688 secs
set: 0.00277495384216 secs
mixed: 0.00166988372803 secs
即,將一組10000個單詞與一組250,000個單詞匹配比匹配相同250,000個單詞列表中相同10000個單詞的列表快17085 X. 使用源列表和成員資格測試集合比單獨的未排序列表快28,392 X.
對於成員資格測試,列表是O(n),並且set和dicts是O(1)用於查找。
結論:為6億行文本使用更好的數據結構!
我不清楚為什么你首先選擇一個列表,但這里有一些選擇:
使用set()可能是一個好主意。 這是非常快的,雖然無序,但有時這正是所需要的。
如果您需要訂購的東西並進行任意查找,您可以使用某種樹: http : //stromberg.dnsalias.org/~strombrg/python-tree-and-heap-comparison/
如果在這里設置少量誤報的成員資格測試或者可以接受,你可以查看一個布隆過濾器: http : //stromberg.dnsalias.org/~strombrg/drs-bloom-filter/
根據你正在做的事情,特里可能也會非常好。
你可以在這里做兩個改進。
dequeue
,因為它的追加性能優於列表。 下面是一個基於我的建議的示例實現(選擇生成器,因為我無法想象你需要在內存中同時使用所有這些單詞)。
from itertools import chain
d = set(['a','b','c']) # Load our dictionary
f = open('c:\\input.txt','r')
# Build a generator to get the words in the file
all_words_generator = chain.from_iterable(line.split() for line in f)
# Build a generator to filter out the non-dictionary words
matching_words_generator = (word for word in all_words_generator if word in d)
for matched_word in matching_words_generator:
# Do something with matched_word
print matched_word
# We're reading the file during the above loop, so don't close it too early
f.close()
input.txt中
a b dog cat
c dog poop
maybe b cat
dog
產量
a
b
c
b
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.