在字符串中找到字符/单词的上下文句子

7 投票
3 回答
1984 浏览
提问于 2025-04-17 19:46

我想用Python从一个字符串中提取包含特定子字符串的句子。

我有一个字符串(一个学术摘要)和一个高亮列表,里面有开始和结束的索引。例如:

{
  abstract: "...long abstract here..."
  highlights: [
    {
      concept: 'a word',
      start: 1,
      end: 10
    }
    {
      concept: 'cancer',
      start: 123,
      end: 135
    }
  ]
}

我正在遍历每个高亮,找到它在摘要中的开始索引(结束索引其实不重要,因为我只需要找到句子中的位置),然后我需要找出这个索引所在的句子。

我可以使用 nltk.tokenize.sent_tokenize 把摘要分割成句子,但这样做会让索引位置变得没用了。

我该怎么解决这个问题呢?我想正则表达式是一个选择,但nltk的分词器看起来很不错,不用它有点可惜……或者可以通过找到上一个句号/感叹号/问号之后的字符数来重置开始索引?

3 个回答

0

另一个选择(虽然很难说这种方法在处理不同格式的文本时有多可靠),就是把文本拆分成一个个句子,然后逐个进行测试:

re.split('(?<=\?|!|\.)\s{0,2}(?=[A-Z]|$)', text)
1

我假设你所有的句子都是以这三个字符之一结尾的:!?.

接下来,可以遍历高亮列表,创建一个正则表达式组:

(?:list|of|your highlights)

然后将你的整个摘要与这个正则表达式进行匹配:

/(?:[\.!\?]|^)\s*([^\.!\?]*(?:list|of|your highlights)[^\.!\?]*?)(?=\s*[\.!\?])/ig

这样,你就可以在每次匹配的第一个子组中找到包含至少一个高亮内容的句子(RegExr)。

6

你说得对,在这种情况下,NLTK的分词器确实是最合适的选择,因为它能很好地处理几乎所有的句子分隔,包括以“引号”结束的句子。你可以这样做(paragraph来自随机生成器):

首先,

from nltk.tokenize import sent_tokenize

paragraph = "How does chickens harden over the acceptance? Chickens comprises coffee. Chickens crushes a popular vet next to the eater. Will chickens sweep beneath a project? Coffee funds chickens. Chickens abides against an ineffective drill."
highlights = ["vet","funds"]
sentencesWithHighlights = []

最直观的方法:

for sentence in sent_tokenize(paragraph):
    for highlight in highlights:
        if highlight in sentence:
            sentencesWithHighlights.append(sentence)
            break

不过,使用这种方法实际上我们会有一个3层嵌套的for循环。这是因为我们首先检查每个sentence,然后检查每个highlight,最后再检查sentence中的每个子序列是否包含highlight

我们可以获得更好的性能,因为我们知道每个高亮的起始索引:

highlightIndices = [100,169]
subtractFromIndex = 0
for sentence in sent_tokenize(paragraph):
    for index in highlightIndices:
        if 0 < index - subtractFromIndex < len(sentence):
            sentencesWithHighlights.append(sentence)
            break
    subtractFromIndex += len(sentence)

无论如何,我们得到:

sentencesWithHighlights = ['Chickens crushes a popular vet next to the eater.', 'Coffee funds chickens.']

撰写回答