Python:如何在文本中找到 n-gram 模式?
Posted
技术标签:
【中文标题】Python:如何在文本中找到 n-gram 模式?【英文标题】:Python: How to find n-gram patterns in the text? 【发布时间】:2012-03-06 08:57:12 【问题描述】:我有一个可以任意长的字符串
s = 'Choose from millions of possibilities on Shaadi.com. Create your profile, search&contact; your special one.RegisterFree\xa0\xa0\xa0unsubscribing reply to this mail\xa0\n and 09times and this is limited time offer! and this is For free so you are saving cash'
我有一个垃圾邮件列表,可能像
p_words = ['cash', 'for free', 'limited time offer']
我只想知道输入文本中是否存在模式以及存在多少次?
只有一个字就变简单了
import re
p = re.compile(''.join[p_words]) # correct me if I am wrong here
m = p.match(s)
但它可能是bi-gram, tri-gram or n-gram
我们如何处理这个问题?
【问题讨论】:
如果您需要不区分大小写的关键字搜索,请参阅my answer that shows the difference between full Unicode casefolding and mere.lower()
method
【参考方案1】:
p = re.compile('|'.join(re.escape(w) for w in p_words))
p
将匹配p_words
中的任何字符串。
【讨论】:
没有理由不这样做。 @J.F.Sebastian 如果您将re.finditer
或re.findall
与生成的正则表达式一起使用。
@Amber: re.find*
枚举匹配项,但仍然自己不回答“多少次”。
@JFSebastian - 鉴于 OP 在不针对 ngram 时已经在使用正则表达式来解决他们的问题,因此假设他们能够根据需要实现计数部分似乎是合乎逻辑的。跨度>
【参考方案2】:
如果文字和字数不是很大可以从example开始:
d = w: s.count(w) for w in p_words if w in s
# -> 'cash': 1, 'limited time offer': 1
您可以将其性能与:
import re
from collections import Counter
p = re.compile('|'.join(map(re.escape, p_words)))
d = Counter(p.findall(s))
# -> Counter('limited time offer': 2, 'cash': 2)
将其速度与fgrep
进行比较以供参考。它应该能够快速匹配输入流中的多个字符串:
$ grep -F -o -f patternlist.txt largetextfile.txt | sort | uniq -c
输出
2 cash
2 limited time offer
【讨论】:
感谢@J.F.Sebastian 告诉我存在计数器,我不知道 @daydreamer:注意Counter
不是最快的,如果你使用这个算法:performance comparison【参考方案3】:
正则表达式使用“|”分隔器。将每种情况下的空格替换为 '\W+' 之类的东西,它匹配非字母,我认为你很高兴。
【讨论】:
以上是关于Python:如何在文本中找到 n-gram 模式?的主要内容,如果未能解决你的问题,请参考以下文章