首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >通过Haskell映射求和

通过Haskell映射求和
EN

Stack Overflow用户
提问于 2011-12-19 04:58:04
回答 3查看 1.9K关注 0票数 5

是否有一个标准函数可以对Haskell映射中的所有值求和。我的地图类似于(a,2),(b,4),(c,6)

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-12-19 05:01:18

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

这与foldl' (+) 0 . Map.elems类似,但效率略高一些。(不要忘记撇号-使用foldl或foldr对标准数字类型(Int、Integer、Float、Double等)进行求和。)将建立巨大的块,这将消耗大量内存,并可能导致您的程序溢出堆栈。)

但是,只有足够新的containers版本(>= 0.4.2.0)才包含Data.Map.foldl',您不应该使用cabal install对其进行升级,因为它附带GHC。因此,除非你使用的是GHC7.2或更高版本,否则foldl' (+) 0 . Map.elems是实现这一目标的最佳方式。

您也可以使用Data.Foldable.sum,它可以在Foldable类型类的任何实例上工作,但仍然会在常见的数字类型上构建较大的块。

下面是一个完整的示例:

代码语言:javascript
运行
复制
normalize :: (Fractional a) => Map k a -> Map k a
normalize m = Map.map (/ total) m
  where total = foldl' (+) 0 $ Map.elems m

要使用foldl',您需要导入Data.List。

票数 4
EN

Stack Overflow用户

发布于 2011-12-19 05:02:41

代码语言:javascript
运行
复制
let
    total = foldr (\(_, n) r -> r + n) 0 l
in map (\(x, y) -> (x, y/total) l

其中l是您的地图。

票数 3
EN

Stack Overflow用户

发布于 2011-12-19 05:07:14

简单:

代码语言:javascript
运行
复制
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

打印:

代码语言:javascript
运行
复制
9.0
fromList [("bar",0.2222222222222222),("baz",0.6666666666666666),("foo",0.1111111111111111)]
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8554756

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档