# JoinAcross with multiple associations

I would like to use JoinAcross to combine several lists of associations. Extending an example from the documentation, I'd like to do this:

JoinAcrossList[{{<|a -> 1, b -> X|>}, {<|a -> 1, c -> Y|>}, {<|a -> 1,
e -> Z|>}}, Key[a]]


Of course, this fails. I have a way of doing this but am wondering if there is anything built-in that would do it or perhaps a more efficient way.

My solution is to use this:

JoinAcrossList[{{<|a -> 1, b -> X|>}, {<|a -> 1, c -> Y|>}, {<|a -> 1, e -> Z|>}}, Key[a]]


Where

JoinAcrossList[associations_List, joinKey_] := Fold[JoinAcross[#1, #2, joinKey] &, associations[], Drop[associations, 1]];


The above example gives this:

In[]:= JoinAcrossList[{{<|a -> 1, b -> X|>}, {<|a -> 1,
c -> Y|>}, {<|a -> 1, e -> Z|>}}, Key[a]]

Out[]= {<|a -> 1, b -> X, c -> Y, e -> Z|>}


Which is the desired result. It also works for the case where the list contains only two elements such as this example:

JoinAcrossList[{{<|a -> 1, b -> X|>}, {<|a -> 1, c -> Y|>}}, Key[a]]


As I write this, I realize that a more efficient combination would probably split this into multiple pairs and then perform successive combinations of those. Would be nice to have a built-in function for this if the number of elements in the list is large.

I can see how to divide a list of elements into pairs using something like the following but not yet sure how to evaluate starting at the lowest elements and then building back up.

NestWhile[Partition[#, 2, 2, {1, 1}, {}] &, Range,Ceiling[Length[#]/2] != 1 &]

• What exactly is your question? How to do an efficient implementation of the function JoinAcrossList? – Anton Antonov Jun 2 at 3:54
• Yes, I'm wondering if there is a more efficient way to do this with some built in operators. What I have works. – Mark R Jun 2 at 7:21
• Just as a small tip: Fold[f, list] is equivalent to Fold[f, First[list], Rest[list]]. – Sjoerd Smit Jun 2 at 9:20
• Thanks for the tip! – Mark R Jun 2 at 17:57

JoinAcrossList1[list_, key_] := Fold[JoinAcross[#1, #2, key] &, list][]

JoinAcrossList1[{{<|a -> 1, b -> X|>}, {<|a -> 1, c -> Y|>}, {<|a -> 1, e -> Z|>}}, Key[a]]


<|a -> 1, b -> X, c -> Y, e -> Z|>

This uses binary subdivision and recursion, but I doubt that it will be faster.

ClearAll[f];
f[list_, key_] /; Length[list] == 1 := list;
f[list_, key_] /; Length[list] == 2 := {JoinAcross[list[], list[], key]};
f[list_, key_] := f[
Join[
f[list[[;; Quotient[Length[list], 2]]], key],
f[list[[Quotient[Length[list], 2] + 1 ;;]], key]
],
key
]
JoinAcrossList2[list_, key_] := f[list, key][[1, 1]]

• I like what you wrote but as you suspected, it isn't actually faster. Will post some timings. – Mark R Jun 2 at 7:28
• For 3 elements to the list: 0.00007 for JoinAcrossList2 and 0.000049 for JoinAcrossList. For 4 elements, where I would think that the split might help, 0.000091 for JoinAcrossList2 and 0.000064 for JoinAcrossList. – Mark R Jun 2 at 7:35