简体   繁体   中英

Prolog Convert a list in a list of lists

I need to convert a list of elements into a list of lists. For example, if i have the list [1,2,3,4] the output must be [[1],[2],[3],[4]], one element per list.

create([],_, _, _).
create([H|T], Aux, X, Result) :-
   append([H], Aux, X),
   Result = [X],
   create(T, X, _, Result).

I always get false... is this even possible to do?

Another possibility to define this relation is by using DCGs. They yield easily readable code when describing lists. Let's stick with the name singletons as suggested by @false in the comments:

singletons([]) -->        % the empty list
   [].                    % is empty
singletons([H|T]) -->     % the head of a nonempty list
   [[H]],                 % is a list on its own
   singletons(T).         % and so is the tail

You can query this directly with phrase/2:

   ?- phrase(singletons([1,2,3,4]),X).
X = [[1],[2],[3],[4]]

Or write a wrapper-predicate with phrase/2 as the single goal:

singletons(L,Ls) :-
   phrase(singletons(L),Ls).

And query that:

   ?- singletons([1,2,3,4],Ls).
Ls = [[1],[2],[3],[4]]

The predicate also works the other way around:

   ?- singletons(L,[[1],[2],[3],[4]]).
L = [1,2,3,4] ? ;
no

As well as the most general query:

   ?- singletons(L,Ls).
L = Ls = [] ? ;
L = [_A],
Ls = [[_A]] ? ;
L = [_A,_B],
Ls = [[_A],[_B]] ?
...

Alternatively you can also define a simple predicate that describes a relation between an arbitrary element and itself in brackets and then use maplist/3 from library(apply) to apply it on every element of a list:

:- use_module(library(apply)).

embraced(X,[X]).

singletons(L,Ls) :-
   maplist(embraced,L,Ls).

This version yields the same results for the above queries. However, it is more efficient. To see that consider the following query from above:

   ?- singletons(L,[[1],[2],[3],[4]]).
L = [1,2,3,4]

Above you had to enter ; to make Prolog search for further solutions and subsequently fail (indicated by no ). With this version there are no unnecessary choice points left and Prolog is succeeding deterministically for the query.

Try this

create([],[]).

create([H|T],[[H]|T2]):- create(T,T2).

I tried

?- create([1,2,3,4],X).

and the result was

X = [[1], [2], [3], [4]].

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM