哈斯克尔地图的总结

时间:2011-12-18 20:58:04

标签: haskell map

是否有标准函数来对Haskell映射中的所有值求和。我的地图读取的内容有[(a,2),(b,4),(c,6)]?

基本上我要做的是归一化频率分布。因此,上图中键的值是a,b,c的计数。我需要将它们标准化为[(a,1/6),(b,1/3),(c,1/2)]

3 个答案:

答案 0 :(得分:4)

如果您将Data.Map导入为Map.foldl' (+) 0,则可以执行M.foldl'(或M。)

这就像foldl' (+) 0 . Map.elems,但效率稍高。 (不要忘记撇号 - 使用foldl或foldr与标准数字类型(Int,Integer,Float,Double等)进行求和会产生巨大的thunk,这将占用大量内存并可能导致程序溢出堆栈。)

但是,只有containers(> = 0.4.2.0)的最新版本包含Data.Map.foldl',您不应该使用cabal install升级它,因为它带有GHC。因此,除非您使用GHC 7.2或更高版本,否则foldl' (+) 0 . Map.elems是实现此目的的最佳方法。

您还可以使用Data.Foldable.sum,它适用于Foldable类型类的任何实例,但仍会在常见的数字类型上构建大量的thunk。

这是一个完整的例子:

normalize :: (Fractional a) => Map k a -> Map k a
normalize m = Map.map (/ total) m
  where total = foldl' (+) 0 $ Map.elems m

您需要导入Data.List才能使用foldl'

答案 1 :(得分:3)

let
    total = foldr (\(_, n) r -> r + n) 0 l
in map (\(x, y) -> (x, y/total) l

l是你的地图。

答案 2 :(得分:3)

简单:

import qualified Data.Map as M

sumMap = M.foldl' (+) 0

normalizeMap m =
  let s = sumMap m in
    M.map (/ s) m

main = do
  let m = M.fromList [("foo", 1), ("bar", 2), ("baz", 6)]
  (print . sumMap) m
  (print . normalizeMap) m

打印:

9.0
fromList [("bar",0.2222222222222222),("baz",0.6666666666666666),("foo",0.1111111111111111)]