joining lists based on content

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!

• 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 5, 2013 at 14:57
• What is the expected output if the second list is: {a, b, c, g, {d,e,f}, h} May 5, 2013 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 5, 2013 at 15:09
• Can you answer my question, please? May 5, 2013 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 5, 2013 at 15:17

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}} *)

• 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 5, 2013 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 5, 2013 at 16:02
• Ah, got it. Thanks! Great!
– mgm
May 5, 2013 at 16:04

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}}