我有一个巨大的.txt.gz文件,其中包含约800kb的单词和分数值,每行格式化为“值字”并按字排序。查找给定单词值的最快方法是什么?
我可以使用以下方式阅读文件:
import gzip
f = gzip.open('somefile.txt.gz', 'rb')
file_content = f.read()
最快的方法是某种二进制搜索吗?
示例数据:
0.090909 chevre#n#1
0.058824 chevron#n#1
0.071429 chevron#n#2
0.071429 chevrotain#n#1
0.166667 chewa#n#1
答案 0 :(得分:1)
二进制搜索是一种有效的方式来做这样的事情,但是你仍然需要将数据从文本(毕竟只是一堆字节)移动到一些其他数据结构,如列表。如果您的程序具有较短的生命周期,或者没有长期内存限制,那么在启动时(或者在适当的时候)将整个内容加载到Python dict
中(或许)可能更快:< / p>
# This may not work exactly right for your file format, but you get the idea.
lookup = {}
for line in f:
if line:
value, key = line.trim().split():
lookup[key] = value
然后使用Python的内置词典访问它,这很好又快:
def get_value(word):
return lookup.get(word)
修改强>
如果您唯一的选择是在每个单词的整个文件中读取,并且您正在搜索许多单词,那么通过实施一个聪明的搜索算法节省的时间可能与您的时间相比有些微不足道花一遍又一遍地打开和阅读文件。你真正想要的是一个数据库,它实际上可以快速处理这类事情。也就是说,根据这些参数,如果我不得不使用文件系统,我可能会做这样的事情:
import bisect
# Define searchable (word, value) tuples for every word in the file.
# I'm assuming your files are sorted, but if not, sort this list (SLOW!!)
words = [(w[1], w[0]) for w in (line.strip().split() for line in f if line)]
# Binary search for the word and return its associated value.
def get_value(word):
idx = bisect.bisect_left(words, (word,None)) # Tuples compare element-wise
if idx != len(words) and words[idx][0] == word:
return words[idx][1]
raise ValueError('word not found')
最后,我注意到你正在使用gzip压缩文件,如果存储空间有问题,这是明智的,但它会使你的进程更慢。我必须再次建议一个数据库。无论如何,我不知道你是否在这里遇到麻烦,但为了以防万一,阅读gzipped文件并不比阅读普通文件更“难”。只需看看gzip module即可。基本上,gzip文件就像常规文件一样工作,所以你仍然可以编写for line in file
等等。