# How to merge data?

I have some group of data with different classes,in the form of below:

{{2, 3} -> 1, {1, 5} -> 1, {1, 1} -> 2, {2, 2} -> 2}

I need to merge the data of same class.Like this:

{1->{ {2,3},{1,5}},2->{{1,1},{2,2}} }

Merge[#[[2]] -> #[[1]] & /@ a, List] This doesn't work well.

• First, apply Association to your data, then use GroupBy[Identity]. – alancalvitti May 8 '17 at 14:36
• Normal[GroupBy[list, Last->First]] – TheYeda May 8 '17 at 14:37
• @erow, Merge[#[[2]] -> #[[1]] & /@ a, Apply@List] – garej May 8 '17 at 14:55
• Is this close enough to be a duplicate? Gathering of list – Kuba May 8 '17 at 18:19
• You did not explain why the Merge you show did not work well. To get the exact output you show, use Merge[Reverse /@ a, Identity], with Normal applied to the result. The GroupBy approach of @TheYeda is likely to be (much) faster though. – Szabolcs May 8 '17 at 22:35

Using the straightforward way GroupBy

Normal@GroupBy[{{2, 3} -> 1, {1, 5} -> 1, {1, 1} -> 2, {2, 2} -> 2}, Last -> First]

(* {1 -> {{2, 3}, {1, 5}}, 2 -> {{1, 1}, {2, 2}}} *)


Using SequenceCases:

list = {{2, 3} -> 1, {1, 5} -> 1, {1, 1} -> 2, {2, 2} -> 2};
Map[# -> SequenceCases[list, {pat : PatternSequence[_ -> #]} :> First@pat] &,
Union@list[[All, 2]]]

(* {1 -> {{2, 3}, {1, 5}}, 2 -> {{1, 1}, {2, 2}}} *)


Using pattern in ReplaceRepeated (this will work if at most two entries per index i.e. 1 -> or 2 -> are present)

{{2, 3} -> 1, {1, 5} -> 1, {1, 1} -> 2, {2, 2} -> 2} //. {w___, pat1_ -> x_,
y___, pat2_ -> x_, z___} :> {w, x -> {pat1, pat2} y, z}

(* {1 -> {{2, 3}, {1, 5}}, 2 -> {{1, 1}, {2, 2}}} *)


More general form of ReplaceRepeated (works with more than two entries)

list= {{2, 3} -> 2, {1, 5} -> 1, {1, 1} -> 2, {2, 2} -> 1, {3, 3} -> 2};

list//. {{w___, pat1_ -> x_, y___, pat2_ -> x_, z___} :> {w, x -> {pat1, pat2}, y, z},
{w___, x_ -> {pat1 : {__} ..}, y___, pat2_ -> x_, z___} :> {w, x -> {pat1, pat2}, y, z}}

(* {2 -> {{2, 3}, {1, 1}, {3, 3}}, 1 -> {{1, 5}, {2, 2}}} *)

• It's hard to understand. – erow May 9 '17 at 4:54
• @erow use the straightforward way for now. As you will explore some aspects of the language more (patterns and rules etc..) I am sure the two methods will fall into place. The purpose here is to show that there are multiple ways of achieving the task. – Ali Hashmi May 9 '17 at 8:06
data = {{2, 3} -> 1, {1, 5} -> 1, {1, 1} -> 2, {2, 2} -> 2};

#[[1, -1]] -> #[[All, 1]] & /@ GatherBy[data, Last]

(*  {1 -> {{2, 3}, {1, 5}}, 2 -> {{1, 1}, {2, 2}}}  *)

a = {{2, 3} -> 1, {1, 5} -> 1, {1, 1} -> 2, {2, 2} -> 2}

Merge[Reverse /@ a, Apply[List]]


In:

xss = {{2, 3} -> 1, {1, 5} -> 1, {1, 1} -> 2, {2, 2} -> 2};
(*Method 1*)
xss // Map[Reverse] // Merge[#, Join] & // Normal

(*Method 2*)
values = Last /@ xss // Union;
positions[x_] := Position[SparseArray[xss] // Normal, x]
valueToRule[x_] := Rule[x, positions[x]]
values // Map[valueToRule]


Out:

{1 -> {{2, 3}, {1, 5}}, 2 -> {{1, 1}, {2, 2}}}
{1 -> {{1, 5}, {2, 3}}, 2 -> {{1, 1}, {2, 2}}}

data = {{2, 3} -> 1, {1, 5} -> 1, {1, 1} -> 2, {2, 2} -> 2};
data1 = data /. ({x_, y_} -> z_) -> {z -> {x, y}};
Merge[Flatten[Tally[data1][[All, 1]]], Identity]