1
$\begingroup$

I have two nested lists like those

{{a,A},{b,B},{c,C}...{z,Z}}
{{a,1},{c,2}...{t,12}}.

I want to combine them to get a new list that looks like this

{{a,A+1},{c,C+2}...{t,T+12}}

where the first element of each sublist exists in both list 1 and list 2 and the lists are of unequal length. How would I do this?

$\endgroup$
1
$\begingroup$

where the first element of each sublist exists in both list 1 and list 2.

Then I assume both list of same length?

Sort them first, then do

lst1 = {{a, A}, {c, C}, {b, B}, {z, Z}};
lst2 = {{a, 1}, {b, 1}, {c, 3}, {z, 4}};

lst1 = Sort[lst1];
lst2 = Sort[lst2];

 (lst1[[#, 2]] = lst1[[#, 2]] + lst2[[#, 2]]) & /@ Range[Length[lst1]]

 (* {{a, 1 + A}, {b, 1 + B}, {c, 3 + C}, {z, 4 + Z}}*)
$\endgroup$
1
$\begingroup$

Consider

list1 = {{a, A}, {b, B}, {c, C}, {z, Z}};
list2 = {{a, 1}, {c, 2}, {t, 12}};

First, we join the two lists : this way, we can also easily take care of entries without a match. Next, we group the big list by the first entry of each pair :

grouped = GatherBy[Join[list1, list2], #[[1]] &]

Now we have several sublists, each corresponding to a different first entry of the pairs. Finally, we consider each sublist in turn and we return a pair; its first element is the first entry of the first pair of the sublist (same for all, we take the first in case that entry has no matches) and the second element is the sum of all the second entries of the sublist :

{#[[1, 1]], Total[#[[All, 2]]]} & /@ grouped
(*  {{a, 1 + A}, {b, B}, {c, 2 + C}, {z, Z}, {t, 12}} *)
$\endgroup$
  • $\begingroup$ Ok, I'm a noob to Mathematica, so could you please explain how this works? $\endgroup$ – Elly Oct 22 '14 at 8:35
  • $\begingroup$ Please see edit. $\endgroup$ – b.gatessucks Oct 22 '14 at 8:47
1
$\begingroup$

Associations can be used for solving this problem as well. We transform the lists into Associations and merge them with Total for combining common values:

list1 = {{a, A}, {b, B}, {c, C}, {z, Z}};
list2 = {{a, 1}, {c, 2}, {t, 12}};
Merge[{Association[Rule @@@ list1], Association[Rule @@@ list2]}, Total]

(* <|a -> 1 + A, b -> B, c -> 2 + C, z -> Z, t -> 12|> *)

An alternative, maybe faster for long lists:

Total /@ GroupBy[Join[list1, list2], First -> Last]

(* <|a -> 1 + A, b -> B, c -> 2 + C, z -> Z, t -> 12|> *)

Back to a list:

List @@@ Normal[%]

(* {{a, 1 + A}, {b, B}, {c, 2 + C}, {z, Z}, {t, 12}} *)

$\endgroup$
0
$\begingroup$

Never mind, I got it. I found a similar question (How do I obtain an intersection of two or more list of lists conditioned on the first element of each sub-list?) and modified one of the responses.

ReplaceList[{list1, list2}, {{___, {a_, b_}, ___}, {___, {a_, c_}, ___}} :> {a, b + c}]

Edit: My lists are really big (like 1000s of entries) so this is really slow, but it works...eventually...

$\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.