我有一个输入文件,由带有数字和单词序列的行组成,结构如下:
\1-grams:
number w1 number
number w2 number
\2-grams:
number w1 w2 number
number w1 w3 number
number w2 w3 number
\end\
Run Code Online (Sandbox Code Playgroud)
我希望以这样的方式存储单词序列(所谓的n-gram),以便我可以轻松地为每个唯一的n-gram检索两个数字.我现在做的是以下内容:
all = {}
ngrams = {}
for line in open(file):
m = re.search('\\\([1-9])-grams:',line.strip()) # find nr of words in sequence
if m != None:
n = int(m.group(1))
ngrams = {} # reinitialize dict for new n
else:
m = re.search('(-[0-9]+?[\.]?[0-9]+)\t([^\t]+)\t?(-[0-9]+\.[0-9]+)?',line.strip()) #find numbers and word sequence
if m != None:
ngrams[m.group(2)] = '{0}|{1}'.format(m.group(1), m.group(3))
elif "\end\\" == line.strip():
all[int(n)] = ngrams
Run Code Online (Sandbox Code Playgroud)
通过这种方式,我可以通过这种方式轻松快速地找到序列s ='w1 w2'的数字:
all[2][s]
Run Code Online (Sandbox Code Playgroud)
问题是这个存储过程相当慢,特别是当有很多(> 100k)的n-gram时,我想知道是否有更快的方法来实现相同的结果,而不会降低访问速度.我在这里做的事情不是很理想吗?我在哪里可以改进?
提前致谢,
里斯
我会尝试减少正则表达式搜索.
值得考虑其他一些事情:
将所有数据存储在单个字典中可以加快速度; 具有额外层的数据层次结构没有帮助,可能违反直觉.
存储元组可以避免调用.format().
在CPython中,函数中的代码比全局代码更快.
这是它的样子:
def load(filename):
ngrams = {}
for line in open(filename):
if line[0] == '\\':
pass # just ignore all these lines
else:
first, rest = line.split(None, 1)
middle, last = rest.rsplit(None, 1)
ngrams[middle] = first, last
return ngrams
ngrams = load("ngrams.txt")
Run Code Online (Sandbox Code Playgroud)
我想要存储int(first), int(last)而不是存储first, last.这将加快访问速度,但减慢加载时间.所以这取决于你的工作量.
我不同意johnthexii:只要数据集适合内存,在Python中执行此操作应该比与数据库(甚至是sqlite)交谈要快得多.(如果您使用数据库,这意味着您可以执行一次加载而不必重复它,因此sqlite可能最终正是您想要的 - 但您不能使用:memory:database.)