Group Abstract Group Abstract

Message Boards Message Boards

2
|
8.3K Views
|
7 Replies
|
7 Total Likes
View groups...
Share
Share this post:

Use a key collision function to combine results of JoinAcross[ ]?

Posted 9 years ago

In the Wolfram Language Documentation for JoinAcross, there is an example that uses a KeyCollisionFunction to change the keys (labels) that result from a join across operation:

in[]: JoinAcross[{<|a -> 1, b -> X|>}, {<|a -> 1, b -> Y|>}, 
 Key[a], "Inner", KeyCollisionFunction -> Function[x, {left[x], right[x]}]]

This produces:

out[]: {<|a -> 1, left[b] -> X, right[b] -> Y|>}

I have a similar problem, but I would like to Join two arrays (or associations) on Key A, and combine the values associated with Key B. That is...

in[]: JoinAcross[{<|a -> 1, b -> X|>}, {<|a -> 1, b -> Y|>}, 
 Key[a], "Inner",  KeyCollisionFunction -> SOME FUNCTION ]

To produce:

{<|a -> 1, b -> {X, Y}|>}

Note, instead of modifying the keys left[b] and right[b], we keep the original key b and combined the values from left and right, into a list associated with the original key b ->{X, Y}. It seems like there should be a straightforward way to do this, but I am not very handy with the syntax for pure functions. Can anyone explain how to do this?

POSTED BY: Caitlin Ramsey
7 Replies

Yes, I agree it is a simple code, we need a better example to test. From what OP has already said I don't know if we have 2 lists of associations (as JoinAccros requires) or it is just a single list that is supposed to be merged in a fancy way.

In the latter case we can adjust my simple approach:

list = {<|a -> 1, b -> 1|>, <|a -> 1, b -> 2|>, <|a -> 2, b -> 3|>, <| a -> 2, b -> 4|>, <|a -> 3, b -> 4|> (*unmatched addition*)}

Values @ GroupBy[list, Key[a], MapAt[First, Key[a]] @* Merge[Identity]]

{<|a -> 1, b -> {1, 2}|>, <|a -> 2, b -> {3, 4}|>, <|a -> 3, b -> {4}|>}

For a->3 there isn't any mach, should b's value be wrapped with {}?, probably depends of OP's needs too.

Alternatively, the same code but with more readable operators order:

GroupBy[list, Key[a], Merge[Identity] /* MapAt[First, Key[a]] ] // Values
POSTED BY: Kuba Podkalicki

Nice solution for the simple case, however this does not work when there are two different 'a' matches:

MapAt[First, Key[a]]@
 Merge[Identity]@{<|a -> 1, b -> 1|>, <|a -> 1, b -> 2|>, <|a -> 2, 
    b -> 3|>, <|a -> 2, b -> 4|>}

Furthermore you don't have a set of 'left' and 'right' associations. I was playing with Merge and GroupBy, but these don't perform a 'join', which is what she wants (I think)... Some more elaborate example would be necessary to see what is wanted...

POSTED BY: Sander Huisman

I suppose a more general example is needed (this one doesn't need JoinAcross specific features) but here is something what may be good enough:

MapAt[First, Key[a]] @ Merge[Identity] @ {<|a -> 1, b -> X|>, <|a -> 1, b -> Y|>}
<|a -> 1, b -> {X, Y}|>
POSTED BY: Kuba Podkalicki

Hi Caitlin,

I'm pretty sure JoinAcross can not do what you want 'out of the box'. However we can make a function that collects the left and right terms and forms a single key:

ClearAll[MergeLeftRight]
MergeLeftRight[assoc_Association]:=Module[{keys,new,newassoc},
    keys=Cases[Keys[assoc],left[_]|right[_]];
    keys=GatherBy[keys,First];
    new=(First[First[#]]->(assoc/@#))&/@keys;
    newassoc=assoc;
    KeyDropFrom[newassoc,Join@@keys];
    newassoc~Join~Association[new]
]

out=JoinAcross[{<|a->1,b->X,c->3|>,<|a->2,b->3|>},{<|a->1,b->Y,c->2|>,<|a->1,b->z,c->4|>,<|a->2,b->cc,c->1|>},Key[a],"Inner",KeyCollisionFunction->Function[x,{left[x],right[x]}]]
out//Column

out = MergeLeftRight/@out;
out // Column

Let me know if this is what you want...

POSTED BY: Sander Huisman
Posted 9 years ago

I do not always have exactly two, and they are part of many associations, with one, two, or more associations that match on Key a. I want to track more than b, but b happens to be the only one that has the form List. (The values associated with other keys would usually be individual strings.)

POSTED BY: Caitlin Ramsey

Nice! I agree, a more 'expanded' example and requirements would be needed to judge the OP's needs...

POSTED BY: Sander Huisman
POSTED BY: Sander Huisman
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard