9
$\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$ Commented May 8, 2017 at 14:36
  • 2
    $\begingroup$ Normal[GroupBy[list, Last->First]] $\endgroup$
    – TheYeda
    Commented May 8, 2017 at 14:37
  • $\begingroup$ @erow, Merge[#[[2]] -> #[[1]] & /@ a, Apply@List] $\endgroup$
    – garej
    Commented May 8, 2017 at 14:55
  • 1
    $\begingroup$ Is this close enough to be a duplicate? Gathering of list $\endgroup$
    – Kuba
    Commented May 8, 2017 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
    Commented May 8, 2017 at 22:35

6 Answers 6

13
$\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
    Commented May 9, 2017 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
    Commented May 9, 2017 at 8:06
7
$\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$

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$
6
$\begingroup$
a = {{2, 3} -> 1, {1, 5} -> 1, {1, 1} -> 2, {2, 2} -> 2}

Merge[Reverse /@ a, Apply[List]]
$\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$
2
$\begingroup$
r = {{2, 3} -> 1, {1, 5} -> 1, {1, 1} -> 2, {2, 2} -> 2};

Using SequenceCases

SequenceCases[r, x : {Repeated[_ -> a_]} :> (a -> First /@ x)]

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

The above functions because r is already sorted by its last elements. If this is not the case:

r = {{2, 3} -> 1, {1, 5} -> 1, {1, 1} -> 2, {2, 2} -> 2, {3, 4} -> 1};

SequenceCases[SortBy[r, Last], x : {Repeated[_ -> a_]} :> (a -> First /@ x)]

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

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.