List 循环遍历列表并添加到元组

List 循环遍历列表并添加到元组,list,haskell,tuples,List,Haskell,Tuples,我试图创建一个函数,该函数通过字符串数组循环,将单词添加到一个新的元组中,该元组计算单词在文本块中出现的次数。在OO语言中,这很简单——为每个单词及其出现的次数创建一个KV对。我正试图将代码翻译成Haskell,但我认为这并不是那么简单 countWords::[String]->[(String,Int)] 我知道我需要创建一个元组列表,但我不确定如何使用递归遍历传递给函数的列表。对于您在OO中所说的操作,一个相当直接的翻译是递归地在列表中“循环”每个单词,或者更新已有的条目,或将其附加为新的

我试图创建一个函数,该函数通过字符串数组循环,将单词添加到一个新的元组中,该元组计算单词在文本块中出现的次数。在OO语言中,这很简单——为每个单词及其出现的次数创建一个KV对。我正试图将代码翻译成Haskell,但我认为这并不是那么简单

countWords::[String]->[(String,Int)]


我知道我需要创建一个元组列表,但我不确定如何使用递归遍历传递给函数的列表。

对于您在OO中所说的操作,一个相当直接的翻译是递归地在列表中“循环”每个单词,或者更新已有的条目,或将其附加为新的:

registerWord :: String -> [(String, Int)] -> [(String, Int)]
registerWord w ((w',c):ws)
    | w==w'       = (w,c+1) : ws
    | otherwise   = (w',c) : registerWord w ws
registerWord w [] = [(w,1)]
然后对每个给定的字执行该操作,每次更新寄存器。这很容易通过折叠完成:

countWords :: [String] -> [(String, Int)]
countWords = foldr registerWord []
但是,这个列表插入很笨拙,效率也很低(在FP和OO中都是如此),即O(n2)。一个更好的方法是功能模块化地思考:实际上,您希望将相等的单词组合在一起。为此,您需要首先对它们进行排序,以便相等的单词实际上是相邻的。然后,您需要用一个示例替换每组重复项,并计算计数。尼斯功能管道:

countWords :: [String] -> [(String, Int)]
countWords = map (\gp@(w:_) -> (w, length gp)) . group . sort
顺便说一句,该函数中没有要求键为“words”/strings的内容,因此您不妨将签名推广到

countWords :: Ord a => [a] -> [(a, Int)]

(另一种低效的方法更为普遍,只需要
Eq

对您在OO中似乎要说的内容进行相当直接的翻译,就是在列表中递归地“循环”每个单词,要么更新已有的条目,要么将其追加为新条目:

registerWord :: String -> [(String, Int)] -> [(String, Int)]
registerWord w ((w',c):ws)
    | w==w'       = (w,c+1) : ws
    | otherwise   = (w',c) : registerWord w ws
registerWord w [] = [(w,1)]
然后对每个给定的字执行该操作,每次更新寄存器。这很容易通过折叠完成:

countWords :: [String] -> [(String, Int)]
countWords = foldr registerWord []
但是,这个列表插入很笨拙,效率也很低(在FP和OO中都是如此),即O(n2)。一个更好的方法是功能模块化地思考:实际上,您希望将相等的单词组合在一起。为此,您需要首先对它们进行排序,以便相等的单词实际上是相邻的。然后,您需要用一个示例替换每组重复项,并计算计数。尼斯功能管道:

countWords :: [String] -> [(String, Int)]
countWords = map (\gp@(w:_) -> (w, length gp)) . group . sort
顺便说一句,该函数中没有要求键为“words”/strings的内容,因此您不妨将签名推广到

countWords :: Ord a => [a] -> [(a, Int)]

(另一种低效的方法更加通用,只需要
Eq

似乎是
map
的一个简单用例,结合一个计算单词在文本中出现次数的函数。但是请注意,因为Haskell是“引用透明的”,所以您要检查的文本也需要作为参数传递给函数。这似乎是
map
的一个简单用例,结合了一个计算单词在文本中出现次数的函数。但是请注意,因为Haskell是“引用透明的”,所以您要检查的文本也需要作为参数传递给函数。谢谢你的解释!哇!谢谢你的解释!