我是Haskell的新手,我只是想编写一个列表解析来计算列表中每个不同值的频率,但是我在上一部分遇到了麻烦..
到目前为止我有这个:
frequency :: Eq a => [a] -> [(Int,a)]
frequency list = [(count y list,y) | y <- rmdups ]
涉及rmdups的最后一部分出了问题。
count函数接受一个字符,然后是一个字符列表,并告诉你该字符出现的频率,代码如下。
count :: Eq a => a -> [a] -> Int
count x [] = 0
count x (y:ys) | x==y = 1+(count x ys)
| otherwise = count x ys
提前谢谢你。
答案 0 :(得分:14)
在计算频率时,您还可以使用关联数组/有限映射将列表元素中的关联存储到其计数中:
import Data.Map (fromListWith, toList)
frequency :: (Ord a) => [a] -> [(a, Int)]
frequency xs = toList (fromListWith (+) [(x, 1) | x <- xs])
使用示例:
> frequency "hello world"
[(' ',1),('d',1),('e',1),('h',1),('l',3),('o',2),('r',1),('w',1)]
请参阅fromListWith
和toList
的文档。
答案 1 :(得分:11)
由于使用了Ord
Eq
代替sort
而不是frequency :: Ord a => [a] -> [(Int,a)]
frequency list = map (\l -> (length l, head l)) (group (sort list))
{{1}}
答案 2 :(得分:6)
根据要求,这是使用Control.Arrow
的解决方案:
frequency :: Ord a => [a] -> [(Int,a)]
frequency = map (length &&& head) . group . sort
这与 ThePestest 的答案功能相同,但
除外λ f g l -> (f l, g l)
替换为
-- simplified type signature
(&&&) :: (a -> b) -> (a -> c) -> a -> (b, c)
来自Control.Arrow
。如果你想避免导入,
liftA2 (,) :: Applicative f => f a -> f b -> f (a, b)
同样适用(使用(->) r
)的适用实例
答案 3 :(得分:4)
假设rmdups
的类型为
rmdups :: Eq a => [a] -> [a]
然后你错过了一个参数。
frequency :: Eq a => [a] -> [(Int,a)]
frequency list = [(count y list,y) | y <- rmdups list]
但是你得到的错误对诊断有帮助。
答案 4 :(得分:0)
rmdups
nub
功能只是来自Data.List
的{{1}}。
答案 5 :(得分:0)
用rmdups
取代nub list
就像魅力一样为我工作。
答案 6 :(得分:0)
哈哈哈哈,pg上有一个rmdups
。 Graham Hutton撰写的 Haskell编程中的86篇。它是完美的和递归的。它在很多情况下也很方便。
这是我的一行rmdups
,它产生与nub
或Hutton相同的结果。
rmdups ls = [d|(z,d)<- zip [0..] ls,notElem d $ take z ls]
它可以用于计算列表中不同的元素。
dl = "minimum-maximum"
[ (d,sum [1|x<-dl,d == x]) | d<-rmdups dl]
[( 'M',6),( 'I',3),( 'N',1),( 'U',2),( ' - ',1),( '一个',1 ),( 'X',1)]