8
$\begingroup$

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.

$\endgroup$
6
  • $\begingroup$ First, apply Association to your data, then use GroupBy[Identity]. $\endgroup$ – alancalvitti May 8 '17 at 14:36
  • 2
    $\begingroup$ Normal[GroupBy[list, Last->First]] $\endgroup$ – TheYeda May 8 '17 at 14:37
  • $\begingroup$ @erow, Merge[#[[2]] -> #[[1]] & /@ a, Apply@List] $\endgroup$ – garej May 8 '17 at 14:55
  • 1
    $\begingroup$ Is this close enough to be a duplicate? Gathering of list $\endgroup$ – Kuba May 8 '17 at 18:19
  • $\begingroup$ 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. $\endgroup$ – Szabolcs May 8 '17 at 22:35
11
$\begingroup$

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}}} *)
$\endgroup$
2
  • $\begingroup$ It's hard to understand. $\endgroup$ – erow May 9 '17 at 4:54
  • $\begingroup$ @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. $\endgroup$ – Ali Hashmi May 9 '17 at 8:06
6
$\begingroup$
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}}}  *)
$\endgroup$
6
$\begingroup$
a = {{2, 3} -> 1, {1, 5} -> 1, {1, 1} -> 2, {2, 2} -> 2}

Merge[Reverse /@ a, Apply[List]]
$\endgroup$
5
$\begingroup$

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}}}
$\endgroup$
4
$\begingroup$
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]
$\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.