简体   繁体   中英

Prolog combine two lists

For example I have A = [a,b,c,d] and B = [[q,w,e],[r,t],[y,u],[i,o]] and I want to create pairs like that C = [[a,[q,w,e]],[b,[r,t]],[c,[y,u]],[d,[i,o]]]. I can create list of pairs, but I don't want to combine everyone with each other. Is there a easy way to do that? I just can't properly define the problem to Google.

This problem does not seem to make much sense to me, but let's try it:

My first observation is that all three lists are of same length. And that effectively you have here an element-wise mapping like so:

a_b_c(A,B,[A,B]).

Now use maplist/4:

?- As = [a,b,c,d], Bs = [[q,w,e],[r,t],[y,u],[i,o]], maplist(a_b_c, As, Bs, Cs).
As = [a,b,c,d],
Bs = [[q,w,e],[r,t],[y,u],[i,o]],
Cs = [[a,[q,w,e]],[b,[r,t]],[c,[y,u]],[d,[i,o]]].

However, dare I say, I really would consider rather pairs! I cannot see any merit in above representation whatsoever.

key_value_pair(K,V,K-V).

?-  As = [a,b,c,d], Bs = [[q,w,e],[r,t],[y,u],[i,o]], maplist(a_b_c, As, Bs, Cs).
As = [a,b,c,d],
Bs = [[q,w,e],[r,t],[y,u],[i,o]],
Cs = [a-[q,w,e],b-[r,t],c-[y,u],d-[i,o]].

maplist/4 is a common predefined or library predicate. See also this post . In case you do not have it:

maplist(_C_3, [], [], []).
maplist(Cont_3, [A|As], [B|Bs], [C|Cs]) :-
   call(Cont_3, A, B, C),
   maplist(Cont_3, As, Bs, Cs).

I defined the following predicate to solve that task.

merge([X], [Y], [[X,Y]]).
merge([X|L1], [Y|L2], [[X,Y]|L3]):-merge(L1, L2, L3).

The first line is a fact . The result of merging two list with one element each one is the list that only have one element which is a list with two elements X and Y .

The second line states that: the result of merging two lists having at least two elements is a list with the first element equal to a list of two elements (the first element of each list) and the remainder is the result of merging the remainder of the first two lists.

EDIT:

If you want to handle the case of empty lists then you can use this definition:

merge([X], [Y], [[X,Y]]):-!.
merge([], [], []).
merge([X|L1], [Y|L2], [[X,Y]|L3]):-merge(L1, L2, L3).

It is a bit more complex because it uses the cut ! predicate to stop looking for solutions.

Try something like this:

zip( []     , [Y|Ys  , [ nil:Y | Zs ] ) :- % for lists of unequal length,
  zip( [] , Ys , Zs ) .                    %   create unmatched pairs and recurse down
zip( [X|Xs] , []     , [ X:nil | Zs ] ) :- % for lists of unqual lengths,
  zip( Xs , [] , Zs ) .                    %   create unmatched paris and recurs down
zip( [X|Xs] , [Y|Ys] , [ X:Y   | Zs ] ) :- % otherwise
  zip( Xs , Ys , Zs )                      % - pair up and recurse down.
  .                                        %

Other strategies for dealing with source lists of unqual length:

  • fail
  • discard the excess

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