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

Haskell实现单词计数时sort/group未生效问题排查

问题根因

你代码里计数全为1的核心问题是对列表Monad的执行逻辑理解错误,导致排序、分组操作从来没有作用在全量单词集合上,而是逐词单独执行统计:

  • 你写的do代码块是运行在列表上下文里的,第一行ys <- words xs会把输入字符串按空白切分成独立单词列表,每次取出一个单独的单词绑定到ys,执行后续所有逻辑
  • 对每个单独的ys跑正则匹配时,因为输入本身就是单个单词,匹配得到的zs永远是长度为1的单元素列表
  • 后续你对这个只有1个元素的列表做转小写、排序、分组,得到的分组自然也只有1个元素,最终返回的计数永远是1
  • 所有单次执行的结果拼接起来,就成了每个单词都计1的错误输出,看起来就像sort和group没有生效——实际上这两个函数是正常工作的,只是处理的对象从来不是全句所有单词。

另外你的正则表达式还有个隐性问题:Haskell字符串里的反斜杠需要转义,你写的"\d"、"\b"不会被正则引擎识别为数字、单词边界元字符,需要写成"\\d"、"\\b"才能正常匹配。

修复方案

不要逐词切分后再跑正则,直接对原始输入字符串做全局正则匹配,拿到全量合法单词列表后,再统一做转小写、排序、分组统计即可,核心参考代码:

module WordCount (wordCount) where

import qualified Data.Char as C
import qualified Data.List as L
import Text.Regex.TDFA as R

wordCount :: String -> [(String, Int)]
wordCount xs =
  let allWords = R.getAllTextMatches (xs =~ "\\d+|\\b[a-zA-Z']+\\b") :: [String]
      lowered = map (map C.toLower) allWords
  in map (\g -> (head g, length g)) $ L.group $ L.sort lowered

注:上述正则还需要额外调整才能正确过滤单词前后附带的撇号(比如示例里的'PASSWORD 123'会匹配到带前导撇号的'PASSWORD'),你可以根据题目规则再优化正则规则,这部分不影响本次计数全1问题的解决。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 17:18:24