在Haskell中,给定一个列表列表,其中每个子列表包含任意数量的整数,如何编写一个返回所有列表中元素总数的函数?
例如,如果我的列表是:
[[1,2,3],[4,3],[2,1],[5]]
该函数将返回8
,因为列表列表中总共有8个元素。我知道您可以使用length []
来获取正常列表的长度,但是如何使用列表列表呢?我认为解决方案是递归的,但可以使用一些帮助,因为我不熟悉该语言。
答案 0 :(得分:8)
三种方式:
获取每个内部列表的长度,并将它们全部加起来:
GHCi> sum (fmap length [[1,2,3],[4,3],[2,1],[5]])
8
(请注意,这相当于Thomas English's answer:map
fmap
专门用于列表。)
展平列表列表,然后获取长度:
GHCi> length (concat [[1,2,3],[4,3],[2,1],[5]])
8
使用Compose
包装器,这将使length
钻取两层列表。
GHCi> import Data.Functor.Compose
GHCi> length (Compose [[1,2,3],[4,3],[2,1],[5]])
8
(虽然在这里解释到底发生了什么有点棘手 - 简而言之,我们正在利用Compose
有一个Foldable
实例 - 在幕后它归结为某种东西非常像第一个解决方案。)
我认为解决方案是递归的
事实上。只是我们使用的其他函数(fmap
用于列表,sum
,concat
等)执行额外的递归,因此我们不会这样做。必须明确地写出递归算法。
答案 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