I haven't tested this function very thoroughly yet, but I think this should get you started. The idea is to go through one of the lists and replace the elements on the joining key with elements "projected" on the elements from the other list (under the specified sametest). After that, I think you should be able to use the regular JoinAcross
:
joinAcross2[
list1 : {__?AssociationQ},
list2 : {__?AssociationQ},
sameTest_,
key : (_String | _Key),
jspec : ("Inner" | "Outer" | "Left" | "Right") : "Inner"
] := Module[{
vals1 = list1[[All, key]]
},
JoinAcross[
list1,
MapAt[
Function[
element,
SelectFirst[vals1, sameTest[element, #] &, element]
],
list2,
{All, key}
],
key,
jspec
]
];
As you can see, I've only implemented this for joining on a single key.
Test:
In[208]:= joinAcross2[{<|a -> 1, b -> X|>}, {<|a -> 1., c -> Y|>}, Equal, Key[a]]
Out[208]= {<|a -> 1, b -> X, c -> Y|>}
edit
Performance:
If the computation time is prohibitive, you can try to rewrite the MapAt
function inside if that's the limiting step. Right now, we map over the column of a list of associations. You could instead try to compute the column values first and use in-place assignment to modify the original dataset. So we'd replace the MapAt
with something like:
Module[{dataset = list2},
dataset[[All, key]] = Map[
Function[element,
SelectFirst[vals1, sameTest[element, #] &, element]
],
dataset[[All, key]]
];
dataset
]
However, this will only be worthwhile if your sameTest
can be compiled. If that's the case, the Map
should be pretty fast. Try using Compile
to see if you can get a compiled version of Function[element, ...]
.
Merge[{<|a -> 1, b -> X|>, <|a -> 1., c -> Y|>}, First]
orMerge[{<|a -> 1, b -> X|>, <|a -> 1., c -> Y|>}, Last]
? $\endgroup$ – Henrik Schumacher Apr 19 '18 at 9:16N
onto the input?data = { {<|a -> 1, b -> X|>, <|a -> 2, b -> XX|>, <|a -> 3, b -> XXX|>}, {<| a -> 1., c -> Y|>, <|a -> 2, c -> YY|>, <|a -> 3, c -> YYY|>} }; JoinAcross[Sequence @@ N@data, Key[a]]
$\endgroup$ – Henrik Schumacher Apr 19 '18 at 10:16SameTest
, butJoinAcross
does not, unfortunately. $\endgroup$ – Henrik Schumacher Apr 19 '18 at 10:20