是否有标准函数来对Haskell映射中的所有值求和。我的地图读取的内容有[(a,2),(b,4),(c,6)]?
基本上我要做的是归一化频率分布。因此,上图中键的值是a,b,c的计数。我需要将它们标准化为[(a,1/6),(b,1/3),(c,1/2)]
答案 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)]