is it possible to get all elements from list of lists in Prolog?
Something like: We have getElements([[[a,b,[c]],d,e],f,g,[h,[i,j]]],S) and the result is: S = [a,b,c,d,e,f,g,h,i,j] ...
Thanks for help.
is it possible to get all elements from list of lists in Prolog?
Something like: We have getElements([[[a,b,[c]],d,e],f,g,[h,[i,j]]],S) and the result is: S = [a,b,c,d,e,f,g,h,i,j] ...
Thanks for help.
In SWI-Prolog (and maybe others), you can use flatten/2
:
?- flatten([[[a,b,[c]],d,e],f,g,[h,[i,j]]], S).
S = [a, b, c, d, e, f, g, h, i|...].
Note that the SWI-Prolog manual page for flatten/2
includes the following statement:
Ending up needing flatten/3 often indicates, like append/3 for appending two lists, a bad design.
However, the page doesn't say whether there is another native predicate to replace it.
I'm sure a better answer will be supplied.
You asked for all elements of a list of lists. That is, for [[1,2,3],[4]]
this would be the list [1,2,3,4]
. However, for [[[1],[3]]]
this would be the list [[1],[3]]
since [1]
and [3]
are elements. For this reason, flatten/2
is incorrect it gives you [1,3]
as an answer. Also, for 1
it gives [1]
...
Here is a solution using dcg:
seq([]) --> [].
seq([E|Es]) --> [E], seq(Es).
seqq([]) --> [].
seqq([Es|Ess]) --> seq(Es), seqq(Ess).
?- phrase(seqq([[[1],[3]]]), Xs).
Xs = [[1],[3]].
?- phrase(seqq(1), Xs).
false.
This solution now works also for cases like the following:
?- phrase(seqq([S1,S2]), [1,2]).
S1 = [],
S2 = [1,2] ;
S1 = [1],
S2 = [2] ;
S1 = [1,2],
S2 = [] ;
false.
Whereas flatten/2
is completely wrong:
?- flatten([S1,S2],[1,2]).
S1 = 1,
S2 = 2.