6
$\begingroup$

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.

$\endgroup$
  • $\begingroup$ not really a dup but it is a straightforward modificaiton: {#[[1, 1]] , Flatten[ Rest /@ # ]} & /@ Select[GatherBy[ Join[list1, list2, list3] , #[[1]] &], Length[#] > 2 &] $\endgroup$ – george2079 Sep 12 '14 at 17:30
  • $\begingroup$ Thanks for your time. Your modification works exactly like Murta but to three lists. $\endgroup$ – ramesh Sep 12 '14 at 17:53
  • $\begingroup$ Can it be assumed that first elements never repeat within one list? $\endgroup$ – Mr.Wizard Sep 13 '14 at 13:59
7
$\begingroup$
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}} *)
$\endgroup$
  • $\begingroup$ Kugler, your are smart. Your code works exactly the way I wanted. $\endgroup$ – ramesh Sep 12 '14 at 17:52
  • $\begingroup$ @rka thank you. Glad it worked for you. $\endgroup$ – kglr Sep 12 '14 at 17:53
5
$\begingroup$

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}
    |> *)
$\endgroup$
4
$\begingroup$
keys = Alternatives @@ Intersection @@ Map[First, {list1, list2, list3}, {2}]

enter image description here

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

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.