【问题标题】:count appearnce of multi-word substring in some text计算某些文本中多字串的出现次数
【发布时间】:2021-05-01 19:47:17
【问题描述】:

所以对于某些文本中的单个单词子串计数,我可以使用some_text.split().count(single_word_substring)。对于某些文本中的多字子字符串计数,我该如何做到这一点?

例子:

text = 'he is going to school. abc is going to school. xyz is going to school.'
to_be_found = 'going to school'

计数应该是 3。

text = 'he is going to school. abc is going to school. xyz is going to school.'
to_be_found = 'going to'

计数应该是 3。

text = 'he is going to school. abc is going to school. xyz is going to school.'
to_be_found = 'go'

计数应为 0。

text = 'he is going to school. abc-xyz is going to school. xyz is going to school.'
to_be_found = 'school'

计数应该是 3。

text = 'he is going to school. abc-xyz is going to school. xyz is going to school.'
to_be_found = 'abc-xyz'

计数应该是 1。

假设 1: 一切都是小写的。 假设 2: 文本可以包含任何内容。 假设 3: to be found 也可以包含任何东西。比如car with 4 passengersxyz & abc等。

注意:基于 REGEX 的解决方案是可以接受的。我只是好奇是否可以不使用正则表达式(很高兴拥有并且仅适用于将来可能对此感兴趣的其他人)。

【问题讨论】:

  • 您是否尝试过使用re.findall
  • 也许re.findall(fr'\b{to_be_found}\b', text) 并取len 的结果?
  • 我的评论是关于第一句话"he is going to school. abc is going to school."。您需要精确匹配 to_be_found 而不仅仅是子字符串匹配,但您希望将 . 视为可选。将字符串拆分为单词会将. 视为shool. 的一部分,并且在使用school 完成时不会考虑完全匹配。一种处理方法是删除字符串中的所有特殊字符。但是在没有正则表达式的情况下这样做将需要对整个字符串进行迭代(一次一个字符)。然后你可以在<space> to_be_found<space>str.count()
  • 如果您可以使用re.findall() 实现它,这一切都不值得。关于您的最后一条评论,您需要将正则表达式中的. 替换为\.,即school\.,因为单个. 在正则表达式中具有特殊含义
  • 有可能,但不是最优的

标签: python regex string text nlp


【解决方案1】:

这是一个使用正则表达式的有效解决方案:

import re

def occurrences(text,to_be_found):
    return len(re.findall(rf'\W{to_be_found}\W', text))

正则表达式中的大写 W 用于非单词字符,包括空格和其他标点符号。

【讨论】:

  • 让我对几个案例进行测试,然后接受答案。谢谢
【解决方案2】:

设法让它与这段代码一起工作(但它根本不是 Pythonic 方式):

text = 'he is going to school. abc is going to school. xyz is going to school.'
to_be_found = 'going to school'

def find_occurences(text, look_for):
    spec = [',','.','!','?']
    where = 0
    how_many = 0

    if not to_be_found in text:
        return how_many

    while True:
        i = text.find(look_for, where)

        if i != -1: #We have a match
            if (((text[i-1] == " ") and (text[i + len(look_for)] == " ")) #Check if the text is really alone
            or (((text[i-1] in spec) or ((text[i-1] == " "))) and (text[i + len(look_for)] in spec))): #Check if it is not surrounded by special characters such as ,.!?

                where = i + len(look_for)
                how_many += 1
            else:
                where = i + len(look_for)
        else:
            break
    
    return how_many

print("'{}' was in '{}' this many times: {}".format(to_be_found, text, find_occurences(text, to_be_found)))
  1. 第一个条件:(text[i-1] == " ") and (text[i + len(look_for)] == " ") 检查子字符串是否没有被空格包围。
  2. 第二个条件:((text[i-1] in spec) or ((text[i-1] == " "))) and (text[i + len(look_for)] in spec)) 检查子字符串是否没有被任何特殊字符和左边的空格包围。

示例 1:

to_be_found = 'going to school'
Output1: 3

示例 2:

to_be_found = 'going to'
Output2: 3

示例 3:

to_be_found = 'go'
Output3: 0

示例 4:

to_be_found = 'school'
Output4: 3

【讨论】:

  • 如果您有任何不适用的建议或价值观,请评论答案,我可以编辑它:)
  • 感谢您的努力。您对 Pythonic 部分的看法是正确的 :)
【解决方案3】:

你试试这个:

text = 'he is going to school. abc is going to school. xyz is going to school.'
to_be_found = 'going to school'
i=0
r=0
while True :
  if text.find(to_be_found,i) <0 or i>len(text) :
    break
  elif text.find(to_be_found,i) >= 0 :
     r=r+1
     i=text.find(to_be_found,i)+len(to_be_found)


print(r)

【讨论】:

  • 希望对你有所帮助
【解决方案4】:
  1. 搜索子字符串的最佳本地方式仍然是计数。它可以根据需要与多字子字符串一起使用

    text = 'he is going to school. abc is going to school. xyz is going to school.'
    text.count('going to school') # 3
    text.count('going to') # 3
    text.count('school') # 3
    text.count('go') # 3
    

    对于 case 'go',如果你需要 0,你可以搜索 'go'、'go' 或 'go' 来捕获单独的单词

  2. 您也可以编写自己的方法来按字符搜索 https://stackoverflow.com/a/30863956/15080484

【讨论】:

  • text.count('go') 返回 3,但 OP 想要 0 作为结果。它需要是完全匹配的单词。解决方法是在搜索词之前和之后添加空格,但是您将无法匹配句号等特殊字符.
  • 这行不通。这仅适用于单个单词子字符串。对于 go,答案应该是 0,而不是 3。
猜你喜欢
  • 2017-11-13
  • 2020-12-07
  • 2013-12-25
  • 1970-01-01
  • 1970-01-01
  • 2017-10-09
  • 2010-11-12
  • 1970-01-01
相关资源
最近更新 更多