计算列表中每个不同元素出现的次数

问题描述 投票:0回答:7

我正在尝试编写一个列表理解来计算列表中每个不同值的频率,但我在最后一部分遇到了麻烦。

到目前为止我有这个:

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
haskell
7个回答
24
投票

您还可以在计算频率时使用关联数组/有限映射来存储列表元素与其计数的关联:

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
的文档。


15
投票

我不得不使用

Ord
代替
Eq
,因为使用了
sort

frequency :: Ord a => [a] -> [(Int,a)] 
frequency list = map (\l -> (length l, head l)) (group (sort list))

7
投票

根据要求,这是使用

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 实例)


5
投票

假设

rmdups
具有类型

rmdups :: Eq a => [a] -> [a]

那么你就缺少了它的参数。

frequency :: Eq a => [a] -> [(Int,a)] 
frequency list = [(count y list,y) | y <- rmdups list]

但是您遇到的错误将有助于诊断。


1
投票

您的

rmdups
功能只是来自
nub
Data.List


-1
投票

rmdups
替换
nub list
对我来说就像一个魅力。


-1
投票

哈哈哈哈第 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)]

© www.soinside.com 2019 - 2024. All rights reserved.