Reputation: 155
In Haskell, given a list of lists, where each sublist contains any number of integers, how can I write a function that returns the total number of elements in all the lists?
For example if my list is:
[[1,2,3],[4,3],[2,1],[5]]
The function would return 8
, since there are 8 total elements in the list of lists. I know you can use length []
to get the length of a normal list, but how do I do this with a list of lists? I would assume the solution to be recursive, but could use some help, since I am new to the language.
Upvotes: 1
Views: 7662
Reputation: 714
So all you need is to treat each list in the list as separate. What tools can do that? As Adam Smith demonstrates foldr is probably the tool of choice however fmap looks good, too and may be shorter. What other tools are there? One of my favorites, the list comprehension. The basic list comprehension lets you process each element of a list in turn. For yours:
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
Upvotes: 0
Reputation: 54163
One additional (pedantic) solution using folds:
foldr ((+) . foldr ((+) . const 1) 0) 0
-- or more simply:
foldr ((+) . length) 0
This incredibly ugly fold generalizes to:
sum [1 | xs <- xss, x <- xs]
which is certainly easier to read.
Upvotes: 4
Reputation: 34378
Three ways:
Get the length of each inner list, and sum them all:
GHCi> sum (fmap length [[1,2,3],[4,3],[2,1],[5]])
8
(Note this is equivalent to Thomas English's answer: map
is fmap
specialised to lists.)
Flatten the list of lists, and then get the length:
GHCi> length (concat [[1,2,3],[4,3],[2,1],[5]])
8
Use the Compose
wrapper, which will make length
drill through the two layers of lists.
GHCi> import Data.Functor.Compose
GHCi> length (Compose [[1,2,3],[4,3],[2,1],[5]])
8
(While explaining exactly what is going on here is a little bit tricky -- in a nutshell, we are exploiting that Compose
has a Foldable
instance -- behind the scenes it boils down to something very much like the first solution.)
I would assume the solution to be recursive
Indeed. It's just that the additional recursion is performed by the other functions we use (fmap
for lists, sum
, concat
, etc.), and so we don't have to write the recursive algorithms explicitly.
Upvotes: 9
Reputation: 231
You should check out how to use the 'map' function. Learn You a Haskell is a good resource to learn more!
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
Upvotes: 4