0

I have lists created by other processing steps, which are basically constituted by elements like this:

{a, b, c, {d,e,f}, g, h}  (*this is the typical element in the first list*)

and

 {a, b, c, {d,e,f}, i, l} (*this one of the second*)

What I'd like to do to is: for each element in the first list, each time that a,b,c,{d,e,f} are the same, join the elements and obtain a list of elements like:

 {a, b, c, {d,e,f}, g, h, i, l}.

a,b,c,{d,e,f} are guaranteed to be in the same position, but of course they vary in value and order, hence the matching.

Any ideas?

Additionally, it would be great to do this in a "fast and efficient" way, since the lists I'll deal with will be rather long.

Thanks!

EDIT: to make the question clearer.

list1= {{a,b,c,{d,e,f},10,21},{m,n,p,{r,s,t},14,64}}
list2= {{m,n,p,{r,s,t},12},{a,b,c,{d,e,f},16}}

I would like to obtain:

{{a,b,c,{d,e,f},10,21,16},{m,n,p,{r,s,t},14,64,12}}

Thanks!

mgm
  • 1,029
  • 7
  • 15
  • So you want to line up corresponding sublists of list1 with those of list2 and join only if the a,b,c... are the same? Or do you want to search and gather from just a single list? – rm -rf May 05 '13 at 14:57
  • What is the expected output if the second list is: {a, b, c, g, {d,e,f}, h} – Dr. belisarius May 05 '13 at 14:59
  • Hi, belisarius:letters are just placeholders: the key idea is just to put the data together. rm-rf: I have 2 lists whose elements are those outlined there. a,b,c,{d,e,f} are the same (in Math, AFAIK, the same symbol represents the same thing ;)) – mgm May 05 '13 at 15:09
  • Can you answer my question, please? – Dr. belisarius May 05 '13 at 15:15
  • Ok. Assume list A = {{a, b, c, {d,e,f}, g, h}, {l, m, n, {o,p,q}, r, s}, {u, v, w, {x,y,z}, a, b}} and list B = {{a, b, c, {d,e,f}, i, j}, {u, v, w, {x,y,z}, d, e}, {a, b, c, {d,e,f}, k, l}, {q, r, s, {o,p,q}, u, v}} — Now, do you want the {a,b,c... in A to be combined only with the first {a,b,c... in B (same position) or with both instances in B? What to do with elements that don't match (e.g. {q,r,s... in B)? Discard them or include them as is? – rm -rf May 05 '13 at 15:17
  • Ah, I see. I forgot to mention that a given set a,b,c,{d,e,f} would appear just once in both lists, but not forcibly in the same position in both. Sorry, does this clear up the question? – mgm May 05 '13 at 15:22
  • belisarius, I tried to explain better my question above, does this answer you question too? – mgm May 05 '13 at 15:35
  • @mag Ok, that clears up most of it; a couple more: 1) Are all the sets present in both lists or can some be missing? 2) Do you care about the order in which the sublists are present? – rm -rf May 05 '13 at 15:46
  • @rm-rf 1) sets {a,b,c,{d,e,f}} can be missing, 2) I do not particularly care, in the worst case I can do a SortBy on the element of interest. Thanks! – mgm May 05 '13 at 15:48
  • Related?: http://mathematica.stackexchange.com/q/16450/121 – Mr.Wizard May 05 '13 at 16:30
  • @Mr.Wizard Admitting I understand the question, I don't think so. – mgm May 05 '13 at 16:41

2 Answers2

4

This is an easy application of Gather and replacement rules. Assuming your two lists are:

list1 = {{a, b, c, {d, e, f}, g, h}, {l, m, n, {o, p, q}, r, s}, {u, v, w, {x, y, z}, a, b}};
list2 = {{a, b, c, {d, e, f}, i, j}, {u, v, w, {x, y, z}, d, e}};

then you can join them as desired with

Gather[list1 ~Join~ list2, #1[[;; 4]] == #2[[;; 4]] &] /. 
    {{{h__, m_List, t1__}, {h__, m_List, t2__}} :> {h, m, t1, t2}, {l : {__, _List, __}} :> l}

(* {{a, b, c, {d, e, f}, g, h, i, j}, {l, m, n, {o, p, q}, r, s}, 
    {u, v, w, {x, y, z}, a, b, d, e}} *)
rm -rf
  • 88,781
  • 21
  • 293
  • 472
  • Hi, That works great, but I don't understand the last part of the substitution rule, could you explain it? (the one with {l:{h__,m_List,t__}}:>l} – mgm May 05 '13 at 15:59
  • @mag That's just to strip one outer {} from an inner expression (see what happens to {l, m, n...} without that rule). I made a specific rule so that other genuine double lists (if any) won't accidentally get stripped. – rm -rf May 05 '13 at 16:02
  • Ah, got it. Thanks! Great! – mgm May 05 '13 at 16:04
2

In version 10+, you can use Merge

Join @@@ Normal @ Merge[Join @@ # &][(#[[;;4]]->#[[5;;]])& /@ Join[list1, list2]]

{{a, b, c, {d, e, f}, 10, 21, 16}, {m, n, p, {r, s, t}, 14, 64, 12}}

or GroupBy:

Join @@@ Normal @ GroupBy[{#[[;;4]], #[[5;;]]}& /@ Join[list1, list2], 
  First->Last, Join @@ #&]

{{a, b, c, {d, e, f}, 10, 21, 16}, {m, n, p, {r, s, t}, 14, 64, 12}}

kglr
  • 394,356
  • 18
  • 477
  • 896