7
$\begingroup$

Suppose I have a list of rules whose keys are not of identical structure (in my case, the keys are either lists of at least one symbol or symbols alone):

rules = {{a} -> 1, {b, c} -> 1, d -> 2, {e, f} -> 2, {g, g} -> 3, g -> 4};

The aim is to get all keys with matching values grouped together to end up with

newRules = {{a, b, c} -> 1, {d, e, f} -> 2, {g, g} -> 3, {g} -> 4};

I have what seems to me to be a hacky attempt to do this:

Reverse /@
    Normal[
        Merge[
            Association /@ Reverse /@ rules, Flatten]
        ] == newRules
(* True *)

Are there any better ways to do this?

$\endgroup$
3
  • $\begingroup$ You could use Flatten[#[[;; , 1]]] -> #[[1, 2]] & /@ GatherBy[rules, Last]. $\endgroup$ Jan 4, 2018 at 21:34
  • 1
    $\begingroup$ equally hacky, but different: GroupBy[List @@@ rules, Last -> Most, Flatten] // GeneralUtilities`AssociationInvert $\endgroup$
    – Jason B.
    Jan 4, 2018 at 21:37
  • 1
    $\begingroup$ Reverse[Normal[GroupBy[rules, Last -> First, Flatten]], 2] $\endgroup$
    – Coolwater
    Jan 4, 2018 at 21:56

4 Answers 4

10
$\begingroup$

There are many ways, here's one:

KeyValueMap[#2 -> # &] @ GroupBy[rules, Last -> First, Flatten]
$\endgroup$
6
$\begingroup$
Reverse /@ (Flatten /@ PositionIndex[Association@rules] // Normal) 

{{a, b, c} -> 1, {d, e, f} -> 2, {g, g} -> 3, {g} -> 4}

In addition:

Flatten /@ PositionIndex[Association@rules]

<|1 -> {a, b, c}, 2 -> {d, e, f}, 3 -> {g, g}, 4 -> {g}|>

$\endgroup$
4
$\begingroup$
Reap[Sow @@@ (List @@@ rules), _, Flatten[{#2}] -> #1 &][[-1]]

yields:

{{a, b, c} -> 1, {d, e, f} -> 2, {g, g} -> 3, {g} -> 4}
$\endgroup$
4
$\begingroup$
KeyValueMap[#2 -> #&] @ Merge[Flatten][Reverse /@ rules]

{{a, b, c} -> 1, {d, e, f} -> 2, {g, g} -> 3, {g} -> 4}

Als0

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

{{a, b, c} -> 1, {d, e, f} -> 2, {g, g} -> 3, {g} -> 4}

and

Values @ GroupBy[rules, Last, Flatten @ #[[All, 1]] -> #[[1, -1]]&] 

{{a, b, c} -> 1, {d, e, f} -> 2, {g, g} -> 3, {g} -> 4}

$\endgroup$

Your Answer

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

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