7
$\begingroup$

I've been trying to figure out how to gather or group on a list of a nested associated--and flailing.

Here is a reduced example. I'm interested in performance as the is for a larger example and the operation will be repeated frequently.

Consider:

test = {
   <|"me" -> <|"a" -> 1, "id" -> 2|>, 
   "friends" -> {<|"gender" -> 1, "id" -> 5|>} |>,
   <|"me" -> <|"a" -> 2, "id" -> 6|>, 
   "friends" -> {<|"gender" -> 1, "id" -> 5|>, <|"gender" -> 2, 
      "id" -> 12|>, <|"gender" -> 3, "id" -> 13|>} |>,
  <|"me" -> <|"a" -> 3, "id" -> 8|>, 
   "friends" -> {<|"gender" -> 3, "id" -> 13|>} |>
  }

I want to collect all "me" associations that have the same "friends" "id" together. For example, for the above:

{
 <|"gender" -> 1, 
   "id" -> 5|> -> {<|"a" -> 1, "id" -> 2|>, <|"a" -> 2, "id" -> 6|>},
 <|"gender" -> 2, "id" -> 12|> -> { <|"a" -> 2, "id" -> 6|>},
 <|"gender" -> 3, 
   "id" -> 13|> -> {<|"a" -> 2, "id" -> 6|>, , <|"a" -> 3, 
    "id" -> 8|>}
 }

I've tried many things such as Gather[test, #1[["friends", "id"]] == #2[["friends", "id"]] &]

and some attempts a Sow/Reap.

Can anyone see how to achieve this?

$\endgroup$
2
  • 1
    $\begingroup$ Normal@Merge[Table[friend -> #me, {friend, #friends}] & /@ test, Identity] $\endgroup$
    – Alan
    Commented Jun 14, 2023 at 17:33
  • $\begingroup$ Palm slap to forehead. How did I miss the existence of Merge? Thanks. $\endgroup$ Commented Jun 15, 2023 at 7:42

2 Answers 2

5
$\begingroup$
Normal@
  Merge[
    Map[
      Thread/*MapApply[Rule], 
      Lookup[test, {"friends", "me"}]], 
    Identity]
$\endgroup$
0
5
$\begingroup$
Merge[Identity] @ Map[Thread[#friends -> #me] &] @ test
<|<|"gender" -> 1, "id" -> 5|> -> 
        {<|"a" -> 1, "id" -> 2|>, <|"a" -> 2, "id" -> 6|>},
  <|"gender" -> 2, "id" -> 12|> -> 
        {<|"a" -> 2, "id" -> 6|>},
  <|"gender" -> 3, "id" -> 13|> -> 
       {<|"a" -> 2, "id" -> 6|>, <|"a" -> 3, "id" -> 8|>}|>

You can also do

Merge[Identity] @
 KeyValueMap[AssociationThread] @
   GroupBy[test, Key @ "friends" -> Key @ "me", First]

same result

and a variation on lericr's method

Merge[Identity] @ 
  MapApply[AssociationThread] @ 
    Lookup[{"friends", "me"}] @ test

same result

$\endgroup$
1
  • 1
    $\begingroup$ Merge[Identity]@ MapApply[AssociationThread]@Lookup[{"friends", "me"}]@test appears to be the fastest for a larger example of test. $\endgroup$ Commented Jun 15, 2023 at 7:38

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.