【问题标题】:Count the n-grams that match a pattern using regular expressions使用正则表达式计算匹配模式的 n-gram
【发布时间】:2022-01-10 13:26:49
【问题描述】:

如果我使用:

import re
words = re.findall(r"(?u)\b\w\w+\b", "aaa, bbb ccc. ddd\naaa xxx yyy")
print(words)
print(len(words))

正如预期的那样,我得到:

['aaa', 'bbb', 'ccc', 'ddd', 'aaa', 'xxx', 'yyy']
7

现在我想修改正则表达式,以便也能够计算 2-gram 和 3-gram,同时考虑到标点​​符号和换行符。特别是,在这种情况下,我期望的结果是:

['aaa', 'bbb', 'ccc', 'ddd', 'aaa', 'xxx', 'yyy', 'bbb ccc', 'aaa xxx', 'xxx yyy', 'aaa xxx yyy']
11

如何修改正则表达式才能做到这一点?

【问题讨论】:

    标签: python regex


    【解决方案1】:

    原答案

    import re
    from itertools import chain
    
    s = "aaa, bbb ccc. ddd\naaa xxx yyy"
    result = list(chain(*(re.findall('(?=((?<!\w)\w\w\w+' + ' \w\w\w+' * n + '(?!\w)))', s)
                          for n in range(3))))
    

    输出:

    >>> result
    ['aaa', 'bbb', 'ccc', 'ddd', 'aaa', 'xxx', 'yyy', 'bbb ccc', 'aaa xxx', 'xxx yyy', 'aaa xxx yyy']
    

    改进的答案(感谢 @CasimiretHippolyte 提供有用的 cmets)

    import re
    from itertools import chain
    
    s = "aaa, bbb ccc. ddd\naaa xxx yyy"
    result = list(chain(*(re.findall(r'\b(?=(\w\w\w+' + ' \w\w\w+' * n + '))', s)
                          for n in range(3))))
    

    【讨论】:

    • 注意,由于最后一个量词是贪心的,所以你不需要检查一个单词字符是否以(?!\w)结尾。此外,您可以使用单词边界\b(?=(... 来代替(?&lt;!\w)(您可以将其放在前瞻之外,它只是一个断言并且不消耗字符,它也会立即丢弃大部分无用的位置)在字符串中而不输入前瞻)。
    • @CasimiretHippolyte 非常感谢您的评论!我不确定\b 部分。我无法让它工作。目前我有\b(?=(\w\w\w+....,但是返回的结果是空的
    • 这很奇怪,它不应该改变最终结果:见regex101.com/r/31Sbcd/1
    • @CasimiretHippolyte 确实很奇怪。在这里查看我的测试:tio.run/##rY/BDoIwEETv/…
    • 你需要一个原始字符串:r'\b(?=(.... 否则\b 在字符串中被视为退格字符。
    猜你喜欢
    • 2012-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多