You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python序列匹配算法实现:长重复短语统计需求

问题描述

给定以下句子列表:

errList = [ 
    'Ragu ate lunch but didnt have Water for drinks', 
    'Rams ate lunch but didnt have Gatorade for drinks', 
    'Saya ate lunch but didnt have :water for drinks', 
    'Raghu ate lunch but didnt have water for drinks', 
    'Hanu ate lunch but didnt have -water for drinks', 
    'Wayu ate lunch but didnt have water for drinks', 
    'Viru ate lunch but didnt have .water 4or drinks', 
    'kk ate lunch & icecream but did have Water for drinks', 
    'M ate lunch &and icecream but did have Gatorade for drinks', 
    'Parker ate lunch icecream but didnt have :water for drinks', 
    'Sassy ate lunch and icecream but didnt have water for drinks', 
    'John ate lunch and icecream but didnt have -water for drinks', 
    'Pokey ate lunch and icecream but didnt have Water for drinks', 
    'Laila ate lunch and icecream but did have water 4or drinks', 
]
需求说明

需要统计列表中每个句子里长度超过2个单词的最长短语的出现次数(严格区分大小写),示例输出参考如下:

{ 
    'ate lunch but didnt have': 7, 
    'water for drinks': 7, 
    'ate lunch and icecream': 4, 
    'didnt have water': 3, 
    'didnt have Water': 2  # 区分大小写
}

要求:禁止使用re模块,属于序列匹配范畴,可基于nltk或scikit-learn实现。

技术实现方案

结合你的NLP和scikit-learn基础,我给你梳理两种可行的实现思路:

方案一:使用NLTK生成Ngrams统计

NLTK的ngrams工具可以轻松生成连续的单词短语,步骤如下:

1. 准备工作

先确保安装并导入NLTK相关模块:

from nltk.util import ngrams
from collections import defaultdict

2. 遍历句子生成所有长短语

我们会遍历每个句子,按空格分割成单词序列,然后生成所有长度≥3的连续短语,同时统计每个短语的出现次数:

phrase_counts = defaultdict(int)

for sentence in errList:
    # 按空格分割句子为单词列表(保留原格式,包括特殊字符)
    words = sentence.split()
    sentence_length = len(words)
    # 生成所有长度从3到句子总长度的连续短语
    for phrase_length in range(3, sentence_length + 1):
        # 生成当前长度的所有连续短语
        for gram in ngrams(words, phrase_length):
            phrase = ' '.join(gram)
            phrase_counts[phrase] += 1

3. 整理输出结果

按出现次数降序排序后,即可得到类似示例的结果:

# 按次数从高到低排序
sorted_results = sorted(phrase_counts.items(), key=lambda x: x[1], reverse=True)
# 转换为字典格式
final_result = dict(sorted_results)
print(final_result)

方案二:使用Scikit-learn的CountVectorizer统计

如果你更熟悉scikit-learn,CountVectorizer可以高效处理短语统计,而且不需要手动遍历生成ngrams:

1. 导入模块并配置参数

我们需要自定义分词规则,确保保留原大小写和特殊字符,同时指定ngram的长度范围:

from sklearn.feature_extraction.text import CountVectorizer
from collections import defaultdict

2. 拟合数据并统计短语

# 配置CountVectorizer:ngram范围3到任意长度,不转小写,按非空白字符分词(即保留原单词格式)
vectorizer = CountVectorizer(
    ngram_range=(3, None),
    lowercase=False,
    token_pattern=r'\S+'  # 确保特殊字符和连字符的单词被完整保留
)

# 拟合句子列表,生成词频矩阵
phrase_matrix = vectorizer.fit_transform(errList)

# 提取短语和对应的出现次数
phrase_counts = dict(
    zip(
        vectorizer.get_feature_names_out(),
        phrase_matrix.sum(axis=0).tolist()[0]
    )
)

3. 排序输出

同样按次数降序整理结果:

sorted_results = sorted(phrase_counts.items(), key=lambda x: x[1], reverse=True)
final_result = dict(sorted_results)
print(final_result)

补充说明

  • 两种方案都严格遵循了“禁止使用re模块”的要求,完全基于序列匹配实现
  • 结果会区分大小写和特殊字符(比如:water和water会被视为不同单词,对应的短语也会分开统计)
  • 如果你需要只保留每个句子的最长短语(而不是所有长短语),可以在遍历句子时先找到当前句子的最长短语长度,只统计该长度的短语,修改起来也很简单:
    # 以NLTK方案为例,修改遍历逻辑
    phrase_counts = defaultdict(int)
    for sentence in errList:
        words = sentence.split()
        n = len(words)
        # 从最长可能的短语长度开始找(最小3)
        max_phrase_len = n
        while max_phrase_len >=3:
            # 生成当前长度的所有短语
            current_phrases = [' '.join(words[i:i+max_phrase_len]) for i in range(n - max_phrase_len +1)]
            if current_phrases:
                # 统计这些最长短语
                for p in current_phrases:
                    phrase_counts[p] +=1
                break  # 找到最长长度后停止,不再处理更短的短语
            max_phrase_len -=1
    

内容的提问来源于stack exchange,提问作者NullException

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:59:58