文本中重复短语的Python处理

3 投票
4 回答
6052 浏览
提问于 2025-04-16 08:59

我遇到了一个问题,完全不知道该怎么解决。请给我一些建议。

我有一段文字。非常非常长的文字。我的任务是找出文本中所有重复的短语,这些短语的长度是3,也就是由三个单词组成。

4 个回答

1

我建议你看看NLTK工具包。这个工具是开源的,主要用于自然语言处理的学习。除了更高级的自然语言处理功能,它还提供了很多关于分词的功能和工具。

2

最简单的方法就是把文本读成一个字符串。然后用字符串的split()方法把它分成一个个单词,放到一个列表里。接着,你可以每三个单词切分一次这个列表,并使用collections.defaultdict(int)来记录每个短语出现的次数。

d = collections.defaultdict(int)

d[phrase]+=1

就像我说的,这种方法很粗糙。但肯定能让你入门。

7

看起来你有两个问题。

第一个问题是如何有效地规范化输入。你提到想要找到输入中的所有三字短语,但什么算是一个短语呢?比如说,the black dogThe black, dog? 是不是同一个短语?

一种方法是使用像 re.findall 这样的工具。可是这样做效率不高:它会遍历整个输入,把单词复制到一个列表中,然后你还得处理这个列表。如果你的输入文本很长,这样做会浪费时间和空间。

更好的方法是把输入当作一个流来处理,创建一个生成器,每次提取一个单词。下面是一个例子,它使用空格作为单词之间的分隔符,然后去掉单词中的非字母字符,并把它们转换为小写:

>>> def words(text):
       pattern = re.compile(r"[^\s]+")
       non_alpha = re.compile(r"[^a-z]", re.IGNORECASE)
       for match in pattern.finditer(text):
           nxt = non_alpha.sub("", match.group()).lower()
           if nxt:  # skip blank, non-alpha words
               yield nxt


>>> text
"O'er the bright blue sea, for Sir Joseph Porter K.C.B."
>>> list(words(text))
['oer', 'the', 'bright', 'blue', 'sea', 'for', 'sir', 'joseph', 'porter', 'kcb']

第二个问题是把规范化后的单词分组为三字短语。同样,这里使用生成器会更有效:

>>> def phrases(words):
        phrase = []
        for word in words:
            phrase.append(word)
            if len(phrase) > 3:
                phrase.remove(phrase[0])
            if len(phrase) == 3:
                yield tuple(phrase)

>>> list(phrases(words(text)))
[('oer', 'the', 'bright'), ('the', 'bright', 'blue'), ('bright', 'blue', 'sea'), ('blue', 'sea', 'for'), ('sea', 'for', 'sir'), ('for', 'sir', 'joseph'), ('sir', 'joseph', 'porter'), ('joseph', 'porter', 'kcb')]

这个函数可能还有更简单的版本,但这个效率不错,而且不难理解。

重要的是,把生成器串联在一起只需遍历列表一次,而且不会在内存中创建大的临时数据结构。你可以用结果来构建一个以短语为键的 defaultdict

>>> import collections
>>> counts = collections.defaultdict(int)
>>> for phrase in phrases(words(text)):
        counts[phrase] += 1

这样在计算短语时只需对 text 进行一次遍历。当完成后,找到字典中所有值大于一的条目。

撰写回答