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

从文本文件移除停用词后词频统计仍异常的Prolog代码问题

问题分析与解决方案

核心问题1:正则分割逻辑错误,提取内容非目标单词

你使用re_split("\\w+", String, Words)分割文本,但\w+匹配的是单词字符序列,这会导致re_split将单词作为分隔符,返回的Words列表实际是单词之间的非单词内容(如空格、标点、换行),完全搞反了提取单词的逻辑。

正确做法是用\\W+(匹配非单词字符序列)作为分隔符,这样才能把文本分割成单词列表:

re_split("\\W+", String, Words),

核心问题2:过滤谓词参数不匹配,无法识别停用词

exclude(word_to_ignore, Sorted, RelevantWords)中,Sorted的元素是Word - Count格式的二元组(例如"the"-1),但word_to_ignore(Word)仅接受单个单词作为参数,永远无法匹配,导致过滤失效。

修正方法是让word_to_ignore适配二元组结构,提取其中的单词进行检查:

% 过滤待忽略单词的谓词(适配二元组)
word_to_ignore(Word - _) :-
    ignore_words(IgnoreWords),
    member(Word, IgnoreWords).

额外优化建议

  1. 简化小写转换逻辑,跳过空字符串:
    修正正则后,Words可能包含空字符串(如文本首尾的非单词字符导致),可以在转小写时直接跳过:

    lower_case([], []).
    lower_case([Word|Rest], [Lower|LowerRest]) :-
        string_length(Word, Len), Len > 0,
        string_lower(Word, Lower),
        lower_case(Rest, LowerRest).
    lower_case([_|Rest], LowerRest) :-
        lower_case(Rest, LowerRest).
    
  2. 调整流程顺序,提升可读性:
    先转小写得到纯单词列表,过滤停用词后再生成带计数的二元组,流程更清晰:

    print_top_words(File, N):-
        read_file_to_string(File, String, [encoding(utf8)]),
        re_split("\\W+", String, Words),
        lower_case(Words, LowerWords),
        exclude(word_to_ignore_plain, LowerWords, RelevantWords),
        pairs_keys_values(WordPairs, RelevantWords, [1|_]),
        sort(1, @=<, WordPairs, Sorted),
        merge_words(Sorted, Counted),
        sort(2, @>, Counted, Top_words),
        writef("Top %w words:\nRank\tCount\tWord\n", [N]),
        print_top_words(Top_words, N, 1).
    
    % 纯单词版本的过滤谓词
    word_to_ignore_plain(Word) :-
        ignore_words(IgnoreWords),
        member(Word, IgnoreWords).
    

修正后的完整代码

% 打印高频单词
print_top_words(File, N):-
    read_file_to_string(File, String, [encoding(utf8)]),
    re_split("\\W+", String, Words),
    lower_case(Words, LowerWords),
    exclude(word_to_ignore_plain, LowerWords, RelevantWords),
    pairs_keys_values(WordPairs, RelevantWords, [1|_]),
    sort(1, @=<, WordPairs, Sorted),
    merge_words(Sorted, Counted),
    sort(2, @>, Counted, Top_words),
    writef("Top %w words:\nRank\tCount\tWord\n", [N]),
    print_top_words(Top_words, N, 1).

% 过滤待忽略单词的谓词(纯单词版本)
word_to_ignore_plain(Word) :-
    ignore_words(IgnoreWords),
    member(Word, IgnoreWords).

% 定义待忽略的停用词
ignore_words(['', 'a', 'an', 'the', 'for', 'of', 'and', 'to', 'in', 'is', 'it', 'on', 'that', 'with', 'this', 'you', 'be', 'are', 'at', 'or', 'as', 'if', 'not', 'from']).

% 将单词转为小写,跳过空字符串
lower_case([], []).
lower_case([Word|Rest], [Lower|LowerRest]) :-
    string_length(Word, Len), Len > 0,
    string_lower(Word, Lower),
    lower_case(Rest, LowerRest).
lower_case([_|Rest], LowerRest) :-
    lower_case(Rest, LowerRest).

% 合并相同单词的计数
merge_words([], []):-!.
merge_words([Word - C1, Word - C2|Words], Result):-
    !,
    C is C1 + C2,
    merge_words([Word - C|Words], Result).
merge_words([W|Words], [W|Rest]):-
    merge_words(Words, Rest).

% 打印前N个高频单词
print_top_words([], _, _):-!.
print_top_words(_, 0, _):-!.
print_top_words([Word - Count|Rest], N, R):-
    writef("%w\t%w\t%w\n", [R, Count, Word]),
    N1 is N - 1,
    R1 is R + 1,
    print_top_words(Rest, N1, R1).

main:- 
    print_top_words("SuspiciousEmail.txt", 10).

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 05:05:40