我是Haskell的新手,我必须计算列表中元素的频率并将其返回到键值对列表中,其中key是列表中的元素,而value是它在其中发生的次数。名单。例如:
对于输入[0,2,2,0,2,5,0,2]
,输出应为[(0,3),(2,4),(5,1)]
这里的难点是我们必须做到这一点,除了比较之外,不使用任何预定义的功能。
import Data.Map (fromListWith, toList)
frequency :: (Ord a) => [a] -> [(a, Int)]
frequency xs = toList (fromListWith (+) [(x, 1) | x <- xs])
这有效,但是toList和fromListWith分类为预定义函数。不用使用任何Data.Map函数就可以做到这一点吗?
答案 0 :(得分:2)
尝试这个
freq:: (Ord a) => [a] -> [(a, Int)]
freq [] = []
freq (x: xs) = ins x (freq xs)
where
ins :: (Ord a) => a -> [(a, Int)] -> [(a, Int)]
ins x ((fk, fv): fs) | x == fk = (fk, fv + 1): fs
ins x ((fk, fv): fs) | x < fk = (x, 1): (fk, fv): fs
ins x ((fk, fv): fs) = (fk, fv): ins x fs
ins x [] = (x, 1): []
ins
函数在地图中插入单个元素。
它是递归地穿过地图。
如果当前元素等于键,则将其值递增。
ins x ((fk, fv): fs) | x == fk = (fk, fv + 1): fs
如果当前元素小于键,则将其插入地图。
ins x ((fk, fv): fs) | x < fk = (x, 1): (fk, fv): fs
否则(如果元素更大),它将尝试在地图的尾部插入元素。
ins x ((fk, fv): fs) = (fk, fv): ins x fs
最后一部分是地图为空时的简单处理情况。