[英]How to remove strings containing certain words from list FASTER
有一个句子列表sentences = ['Ask the swordsmith', 'He knows everything']
。 目标是从单词表lexicon = ['word', 'every', 'thing']
删除那些单词。 这可以使用以下列表理解来实现:
newlist = [sentence for sentence in sentences if not any(word in sentence.split(' ') for word in lexicon)]
请注意, if not word in sentence
不是充分条件,因为它还会删除包含词中嵌入了词库中的词的句子,例如word
被嵌入到swordsmith
,而every
和thing
都被嵌入到了everything
。
但是,我的句子列表包含 1.000.000 个句子和 200.000 个单词的词典。 应用提到的列表理解需要几个小时! 因此,我正在寻找一种更快的方法来从包含另一个列表中的单词的列表中删除字符串。 有什么建议? 也许使用正则表达式?
在set
查找。 这使它变得更快,并减轻了包含问题,因为您只在词典中查找整个单词。
lexicon = set(lexicon)
newlist = [s for s in sentences if not any(w in lexicon for w in s.split())]
这是非常有效的,因为w in lexicon
中的w in lexicon
是一个O(1)
操作,以及any
短路。 主要问题是将句子正确拆分为单词。 正则表达式不可避免地会比自定义解决方案慢,但可能是最佳选择,具体取决于您希望对标点符号等的鲁棒性。 例如:
lexicon = set(lexicon)
pattern = re.compile(r'\w+')
newlist = [s for s in sentences if not any(m.group() in lexicon for m in pattern.finditer(s))]
您可以在这里优化三件事:
<>将词典转换为set
,以免in
操作中产生成本。
lexicon = set(lexicon)
<>以最有效的方式检查sentence
与lexicon
交集。 它应该使用set
操作。 这里讨论了集合交集的性能。
[x for x in sentences if set(x.split(' ')).isdisjoint(lexicon)]
<> 使用filter
而不是列表理解。
list(filter(lambda x: set(x.split(' ')).isdisjoint(lexicon), sentences))
最终代码:
lexicon = set(lexicon)
list(filter(lambda x: set(x.split(' ')).isdisjoint(lexicon), sentences))
结果
def removal_0(sentences, lexicon):
lexicon = set(lexicon)
pattern = re.compile(r'\w+')
return [s for s in sentences if not any(m.group() in lexicon for m in pattern.finditer(s))]
def removal_1(sentences, lexicon):
lexicon = set(lexicon)
return [x for x in sentences if set(x.split(' ')).isdisjoint(lexicon)]
def removal_2(sentences, lexicon):
lexicon = set(lexicon)
return list(filter(lambda x: set(x.split(' ')).isdisjoint(lexicon), sentences))
%timeit removal_0(sentences, lexicon)
%timeit removal_1(sentences, lexicon)
%timeit removal_2(sentences, lexicon)
9.88 µs ± 219 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
2.19 µs ± 55.7 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
2.76 µs ± 53.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
笔记。 所以看起来过滤器有点慢,但我还不知道原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.