haskell中的字数统计

5us2dqdw  于 2022-11-14  发布在  其他
关注(0)|答案(2)|浏览(210)

我正在做这个练习:
给定一个短语,计算每个单词在该短语中出现的次数。
在本练习中,您可以期望单词始终为以下之一:
由一个或多个ASCII数字组成的数字(即“0”或“1234”)OR由一个或多个ASCII字母组成的简单单词(即“a”或“they”)OR由一个撇号连接的两个简单单词的缩写(即“it 's”或“they' re”)当计算单词时,您可以假设以下规则:
计数不区分大小写(即“You”、“you”和“YOU”是同一个单词的3次使用)。计数是无序的;测试将忽略单词和计数的排序方式除了缩写形式中的撇号之外,所有形式的标点符号都将被忽略。单词可以用任何形式的空格(即“\t”、“\n”、““)分隔。例如,对于短语“That 's the password:“密码123”!",特工喊道。\n所以我逃走了。计数应该是:
那就是:2.密码:2 123:1叫道:1.专项:1.代理:10:1 i:1逃跑了:1
我的代码:

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 =
  do
    ys <- words xs
    let zs = R.getAllTextMatches (ys =~ "\\d+|\\b[a-zA-Z']+\\b") :: [String]
    g <- L.group $ L.sort [map (C.toLower) w | w <- zs]
    return (head g, length g)

但是它在输入“one fish two fish red fish blue fish”时失败了,它为每个单词输出一个计数,即使是重复的单词,就好像排序和分组没有做任何事情一样。为什么?
我读过this answer,它使用Control.Arrow以一种更高级的方式基本上做了同样的事情。

iecba09b

iecba09b1#

您不需要使用words来拆分行,正则表达式应该可以实现所需的拆分:

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

s2j5cfk02#

wordCount xs =
  do
    ys <- words xs
    let zs = R.getAllTextMatches (ys =~ "\\d+|\\b[a-zA-Z']+\\b") :: [String]
    g <- L.group $ L.sort [map (C.toLower) w | w <- zs]
    return (head g, length g)

使用words将输入xs按空格拆分为单词,使用绑定语句ys <- …在单子列表中迭代这些单词,然后使用正则表达式将每个单词拆分为子词(在示例中,只有一个匹配项),并对列表中的每个子词进行排序和分组。
我相信您基本上可以删除对words的初始调用:

wordCount xs =
  do
    let ys = R.getAllTextMatches (xs =~ "\\d+|\\b[a-zA-Z']+\\b") :: [String]
    g <- L.group $ L.sort [map C.toLower w | w <- ys]
    return (head g, length g)

相关问题