我正在尝试编写一个列表理解来计算列表中每个不同值的频率,但我在最后一部分遇到了麻烦。
到目前为止我有这个:
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
您还可以在计算频率时使用关联数组/有限映射来存储列表元素与其计数的关联:
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
的文档。
我不得不使用
Ord
代替Eq
,因为使用了sort
frequency :: Ord a => [a] -> [(Int,a)]
frequency list = map (\l -> (length l, head l)) (group (sort list))
根据要求,这是使用
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
的 Applicative 实例)
假设
rmdups
具有类型
rmdups :: Eq a => [a] -> [a]
那么你就缺少了它的参数。
frequency :: Eq a => [a] -> [(Int,a)]
frequency list = [(count y list,y) | y <- rmdups list]
但是您遇到的错误将有助于诊断。
您的
rmdups
功能只是来自 nub
的 Data.List
。
用
rmdups
替换 nub list
对我来说就像一个魅力。
哈哈哈哈第 pg 上有一个
rmdups
。 Graham Hutton 的《Haskell 编程》第 86 期。它是完美且递归的。它在很多情况下也很方便。
这是我的一行rmdups
,它产生的结果与
nub
或赫顿的相同。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),('a',1), ('x',1)]