GregH
GregH

Reputation: 5457

Find length of a list of lists

I wrote a predicate which should calculate the length of a list:

 my_length([],0).
 my_length([_|L],N) :- my_length(L,N1), N is N1 + 1.

Can anyone help in adjusting this so that it will take a list of lists and output the total number of elements in the list of lists?

Upvotes: 2

Views: 3225

Answers (4)

repeat
repeat

Reputation: 18726

In this answer we use foldl/4 in combination with Prolog lambda expressions.

:- use_module(library(lambda)).

We define the predicate lists_length/2 like this:

lists_length(Xss,N) :-
   foldl(\Xs^N0^N2^(length(Xs,N1),N2 is N0+N1), Xss, 0,N).

Sample query:

?- lists_length([[a,b,c],[],[d,e]], N).
N = 5.

Upvotes: 1

false
false

Reputation: 10102

I am still not the biggest fan of foldl/4 and thus I find it much more natural to state:

xss_length(Xss, N) :-
   maplist(length,Xss, Ns),
   list_sum(Ns, N).

Still, this does not terminate for Xss = [_,_], xss_length(Xss, 2). But it's a start.

Upvotes: 1

Paulo Moura
Paulo Moura

Reputation: 18663

Both the solution posted @dasblinkenlight and the original code in the question can be made tail-recursive by using accumulators, which would allow running in constant space:

my_length(List, Length) :-
    my_length(List, 0, Length).

my_length([], Length, Length).
my_length([_| Tail], Length0, Length) :-
    Length1 is Length0 + 1,
    my_length(Tail, Length1, Length).

my_length_lol(Lists, TotalLength) :-
    my_length_lol(Lists, 0, TotalLength).

my_length_lol([List| Lists], TotalLength0, TotalLength) :-
    my_length(List, Length),
    TotalLength1 is TotalLength0 + Length,
    my_length_lol(Lists, TotalLength1, TotalLength).

Upvotes: 1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726479

You have most of what you need: add a rule that computes the length of a list of lists that passes the head on to my_length:

my_length_lol([], 0).
my_length_lol([H|L],N) :- my_length(H,Add), my_length_lol(L,N1), N is N1 + Add.

As you can see, my_length_lol ("lol" stands for "List of Lists") is a near exact copy of my_length. The only difference is that it does not ignore list head, and uses my_length rule to compute the length of a sublist.

Demo.

Upvotes: 2

Related Questions