# Combining more than two lists by first column as index

Please bear with me. It might be easy but its been hard for me. I have say three lists:

list1={{1,a,aa},{2,b,bb},{3,c,cc},{4,d,dd},{5,e,ee},{6,f,ff},{7,g,gg},{8,h,hh},{9,i,ii},{10,j,jj}};

list2={{2,.2},{3,.3},{5,.5},{6,.6},{10,.1}};

list3={{1,10,100,1000},{2,20,200,2000},{5,50,500,5000},{6,60,600,6000},
{7,70,700,7000},{9,90,900,9000},{10,100,1000,10000}};


I want the final results as:

result={{2,b,bb,.2,20,200,2000},{5,e,ee,.5,50,500,5000},{6,f,ff,.6,60,600,6000},
{10,j,jj,.1,100,1000,10000}};


I have seen earlier similar question at

How do I obtain an intersection of two or more list of lists conditioned on the first element of each sub-list?

Thanks to Murta for his function

{#[[1,1]],#[[All,2]]}&/@Select[GatherBy[list1~Join~list2,First],Length[#]>1&]


It works pretty well to merge two lists and pretty fast. However, the final format is little different from what I want.

Similarly, there is another post dealing similar issue. Combining two lists

Again, thanks to VLC for his function

Join[list1, List /@ Last /@ Select[list2, MemberQ[First /@ list1, #[[1]]] &], 2]


Again, it works for two lists but pretty slow. I can not make either one to work for my purpose. Any help is greatly appreciated. Please consider seriously before putting some kind of tag like "Duplicate" etc.

Please don't stop answering. This is so common question. We need varieties in answers in terms of simplicity and speed. May be we can extend answers to combine any numbers of lists not just three.

Thank you.

• not really a dup but it is a straightforward modificaiton: {#[[1, 1]] , Flatten[ Rest /@ # ]} & /@ Select[GatherBy[ Join[list1, list2, list3] , #[[1]] &], Length[#] > 2 &] Commented Sep 12, 2014 at 17:30
• Thanks for your time. Your modification works exactly like Murta but to three lists. Commented Sep 12, 2014 at 17:53
• Can it be assumed that first elements never repeat within one list? Commented Sep 13, 2014 at 13:59

Flatten[{#, Rest/@{##2}}]&@@@(Pick[#, Length@# > 2]&/@ GatherBy[Join[list1, list2, list3], First])
(* {{2, b, bb, 0.2, 20, 200, 2000},
{5, e, ee, 0.5, 50, 500, 5000},
{6, f, ff, 0.6, 60, 600, 6000},
{10, j, jj, 0.1, 100, 1000, 10000}} *)

• Kugler, your are smart. Your code works exactly the way I wanted. Commented Sep 12, 2014 at 17:52
• @rka thank you. Glad it worked for you.
– kglr
Commented Sep 12, 2014 at 17:53

Version 10 offers some nice notation to perform the essential work:

{list1, list2, list3} // Map@GroupBy[First->Rest] // KeyIntersection // Merge@Flatten

(* <| 2 -> {b,bb,0.2,20,200,2000}
, 5 -> {e,ee,0.5,50,500,5000}
, 6 -> {f,ff,0.6,60,600,6000}
, 10-> {j,jj,0.1,100,1000,10000}
|> *)


The result is an association, which is usually a good thing. But if the application demands a list instead, a couple more operations will produce it:

% // Normal // Prepend[#2, #]& @@@ # &

(* { {2,b,bb,0.2,20,200,2000}
, {5,e,ee,0.5,50,500,5000}
, {6,f,ff,0.6,60,600,6000}
, {10,j,jj,0.1,100,1000,10000}
} *)


This solution works with any number of lists:

list4 = {{5, "five"}, {6, "six"}};

{list1, list2, list3, list4} // Map@GroupBy[First->Rest] // KeyIntersection // Merge@Flatten

(* <| 5 -> {e,ee,0.5,50,500,5000,five}
, 6 -> {f,ff,0.6,60,600,6000,six}
|> *)

keys = Alternatives @@ Intersection @@ Map[First, {list1, list2, list3}, {2}]


res =
Flatten /@ Transpose[{
Cases[list1, {keys, __}],
Last /@ Cases[list2, {keys, __}],
Rest /@ Cases[list3, {keys, __}]}]


{{2, b, bb, 0.2, 20, 200, 2000}, {5, e, ee, 0.5, 50, 500, 5000}, {6,
f, ff, 0.6, 60, 600, 6000}, {10, j, jj, 0.1, 100, 1000, 10000}}

res == result


True