我有一本字典,包含近一百万个多字词(包含空格的词条)。看起来像
[...,
'multilayer ceramic',
'multilayer ceramic capacitor',
'multilayer optical disk',
'multilayer perceptron',
...]
我想用几千兆字节的文本来计算它们的出现频率。
作为一个小示例,请考虑在Wikipedia页面中对这四个多词表达式进行计数:
payload = {'action': 'query', 'titles': 'Ceramic_capacitor', 'explaintext':1, 'prop':'extracts', 'format': 'json'}
r = requests.get('https://en.wikipedia.org/w/api.php', params=payload)
sampletext = r.json()['query']['pages']['9221221']['extract'].lower()
sampledict = ['multilayer ceramic', 'multilayer ceramic capacitor', 'multilayer optical disk', 'multilayer perceptron']
termfreqdic = {}
for term in sampledict:
termfreqdic[term] = sampletext.count(term)
print(termfreqdic)
这类似于{'multilayer ceramic': 7, 'multilayer ceramic capacitor': 2, 'multilayer optical disk': 0, 'multilayer perceptron': 0}
,但如果词典中包含一百万个条目,则似乎不是最佳选择。
我尝试使用非常大的正则表达式:
termlist = [re.escape(w) for w in open('termlistfile.txt').read().strip().split('\n')]
termregex = re.compile(r'\b'+r'\b|\b'.join(termlist), re.I)
termfreqdic = {}
for i,li in enumerate(open(f)):
for m in termregex.finditer(li):
termfreqdic[m.group(0)]=termfreqdic.get(m.group(0),0)+1
open('counted.tsv','w').write('\n'.join([a+'\t'+v for a,v in termfreqdic.items()]))
这太慢了(最近的i7上1000行文本需要6分钟)。但是,如果我通过替换前两行使用regex
而不是re
,则每1000行文本它会减少到大约12s,这对于我的需求而言仍然很慢:
termlist = open(termlistfile).read().strip().split('\n')
termregex = regex.compile(r"\L<options>", options=termlist)
...
[注意,这并不能完全满足我的要求,因为一个术语可能是另一个术语的子术语,例如示例“多层陶瓷”和“多层陶瓷电容器”(也排除了Find multi-word terms in a tokenized text in Python中的第一次标记化方法)。
这似乎是文本语料库或遗传字符串中序列匹配的常见问题,必须具有众所周知的解决方案。也许可以用一些trie的单词解决(我不介意术语表的初始编译很慢)? las,我似乎并没有在寻找正确的条件。也许有人可以指出正确的方向?
如果您确定只有一个字/索引,您可以这样做吗?
list1 = ['a b c', 'b c', 'a c']
a = 0
word = 'a'
for x in list1:
if word in x:
a += 1
print(a)