2

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.

false
  • 10,264
  • 13
  • 101
  • 209
JohnDow
  • 1,242
  • 4
  • 22
  • 40

3 Answers3

5

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).
false
  • 10,264
  • 13
  • 101
  • 209
2

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.

rareyesdev
  • 2,337
  • 1
  • 25
  • 43
0

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
Nicholas Carey
  • 71,308
  • 16
  • 93
  • 135
  • 2
    This program no longer handles `nil` correctly. Its representation is called **defaulty**. – false May 30 '14 at 20:22