Haskell计算列表列表中的所有元素

时间:2018-03-26 23:52:36

标签: haskell recursion

在Haskell中,给定一个列表列表,其中每个子列表包含任意数量的整数,如何编写一个返回所有列表中元素总数的函数?

例如,如果我的列表是:

[[1,2,3],[4,3],[2,1],[5]]

该函数将返回8,因为列表列表中总共有8个元素。我知道您可以使用length []来获取正常列表的长度,但是如何使用列表列表呢?我认为解决方案是递归的,但可以使用一些帮助,因为我不熟悉该语言。

4 个答案:

答案 0 :(得分:8)

三种方式:

  1. 获取每个内部列表的长度,并将它们全部加起来:

    GHCi> sum (fmap length [[1,2,3],[4,3],[2,1],[5]])
    8
    

    (请注意,这相当于Thomas English's answermap fmap专门用于列表。)

  2. 展平列表列表,然后获取长度:

    GHCi> length (concat [[1,2,3],[4,3],[2,1],[5]])
    8
    
  3. 使用Compose包装器,这将使length钻取两层列表。

    GHCi> import Data.Functor.Compose
    GHCi> length (Compose [[1,2,3],[4,3],[2,1],[5]])
    8
    

    (虽然在这里解释到底发生了什么有点棘手 - 简而言之,我们正在利用Compose有一个Foldable实例 - 在幕后它归结为某种东西非常像第一个解决方案。)

  4.   

    我认为解决方案是递归的

    事实上。只是我们使用的其他函数(fmap用于列表,sumconcat等)执行额外的递归,因此我们不会这样做。必须明确地写出递归算法。

答案 1 :(得分:3)

您应该查看如何使用'map'功能。 Learn You a Haskell是了解更多信息的好资源!

mylist = [[1,2,3],[4,3],[2,1],[5]]

-- Get the length of each sublist with map
sublist_lengths = map length mylist 
-- sublist_lengths = [3, 2, 2, 1]

result = sum sublist_lengths

答案 2 :(得分:2)

使用折叠的另一个(迂腐)解决方案:

foldr ((+) . foldr ((+) . const 1) 0) 0
-- or more simply:
foldr ((+) . length) 0

这种令人难以置信的难看的褶皱概括为:

sum [1 | xs <- xss, x <- xs]

这当然更容易阅读。

答案 3 :(得分:0)

所以你需要的是将列表中的每个列表视为单独的。哪些工具可以做到这一点?正如亚当·斯密所展示的那样,折叠器可能是首选工具,但fmap看起来也很好,而且可能更短。 还有哪些其他工具?我最喜欢的一个,列表理解。 基本列表推导使您可以依次处理列表中的每个元素。 对你的:

yourList = [[1,2,3],[4,3],[2,1],[5]]

[length l | l <- yourList] -- gets the length of each list and

sum [length l | l <- yourList] -- adds up all the lengths produced