文本Python中重复的短语

时间:2010-12-24 14:11:46

标签: python text repeat

我有问题,我不知道如何解决它。请提出一些建议。

我有一个文字。大,大文。任务是找到文本中长度为3(包含三个单词)的所有重复短语。

4 个答案:

答案 0 :(得分: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进行单次传递,因为它会计算短语。完成后,找到字典中值大于1的每个条目。

答案 1 :(得分:2)

最粗略的方法是读取字符串中的文本。执行string.split()并获取列表中的单个单词。然后,您可以按三个单词切片列表,并使用collections.defaultdict(int)来保持计数。

d = collections.defaultdict(int)

d [短语] + = 1

正如我所说,它非常粗糙。但是当然应该让你开始

答案 2 :(得分:1)

我建议看一下NLTK工具包。这是开源的,旨在用于自然语言教学。除了更高级别的NLP功能外,它还有许多令牌化类型的函数和集合。

答案 3 :(得分:0)

这是一个大致的O(n)解决方案,它应该适用于相当大的输入文本。如果速度太慢,您可能希望使用专为文本处理而设计的Perl或纯粹性能的C ++。

>>> s = 'The quick brown fox jumps over the lazy dog'
>>> words = string.lower(s).split()
>>> phrases = collections.defaultdict(int)
>>> for a, b, c in zip(words[:-3], words[1:-2], words[2:]):
...     phrases[(a, b, c)] += 1
... 
>>> phrases
defaultdict(<type 'int'>, {('over', 'the', 'lazy'): 1, ('quick', 'brown', 'fox'): 1, ('the', '
quick', 'brown'): 1, ('jumps', 'over', 'the'): 1, ('brown', 'fox', 'jumps'): 1, ('fox', 'jumps
', 'over'): 1})
>>> [phrase for phrase, count in phrases.iteritems() if count > 1]
>>> []