2
$\begingroup$

I have two associations like this

In[211]:= assoc1 = 
AssociationThread[{a, b, c, d, e, f, g}, {1, 2, 3, 4, 5, 6, 7}]

Out[211]= <|a -> 1, b -> 2, c -> 3, d -> 4, e -> 5, f -> 6, g -> 7|>

In[212]:= assoc2 = 
AssociationThread[{a, b, c, d, f, g, h}, {12, 22, 23, 24, 25, 26, 27}]

Out[212]= <|a -> 12, b -> 22, c -> 23, d -> 24, f -> 25, g -> 26, 
h -> 27|>

Now when i want to merge them by using Identity

In[213]:= Merge[{assoc1, assoc2}, Identity]

Out[213]= <|a -> {1, 12}, b -> {2, 22}, c -> {3, 23}, d -> {4, 24}, 
e -> {5}, f -> {6, 25}, g -> {7, 26}, h -> {27}|>

So here is the point: I want to obtain a value of "0" for the missing values of each association AND in the position according to the ordering of the associations (in this example for key e {5,0} and for key h {0,27} since e is missing in assoc2 and h is missing in assoc1)

However I found a solution by first using a combination of Complement, Union and Intersection to obtain a sample of the unique keys within each association. Then I gave them a value of zero and merged them with each assoc by using Total. Finally I merged them again with Identity and obtained the desired result but that is far away from being an elegant solution....

$\endgroup$
1
  • 2
    $\begingroup$ if you can, you should accept @kglr's answer as the definitive answer. The trick I use with Join is better accomplished with KeyUnion. $\endgroup$
    – Jason B.
    Commented Nov 28, 2018 at 22:53

3 Answers 3

4
$\begingroup$

You can use KeyUnion with 0& as the second argument:

KeyUnion[{assoc1, assoc2}, 0 &]

{<|a -> 1, b -> 2, c -> 3, d -> 4, e -> 5, f -> 6, g -> 7, h -> 0|>,
<|a -> 12, b -> 22, c -> 23, d -> 24, e -> 0, f -> 25, g -> 26, h -> 27|>}

Merge[Identity]@KeyUnion[{assoc1, assoc2}, 0 &]

<|a -> {1, 12}, b -> {2, 22}, c -> {3, 23}, d -> {4, 24}, e -> {5, 0}, f -> {6, 25}, g -> {7, 26}, h -> {0, 27}|>

$\endgroup$
1
$\begingroup$

If you can get a list of all the keys you need, you can fill out your associations to have a default value by joining them with an association of only default values:

allKeys = {a, b, c, d, e, f, g, h};
default = AssociationThread[allKeys -> 0];
fillOut = Join[default, #] &;
Merge[fillOut /@ {assoc1, assoc2}, Identity]

(* <|a -> {1, 12}, b -> {2, 22}, c -> {3, 23}, d -> {4, 24}, 
 e -> {5, 0}, f -> {6, 25}, g -> {7, 26}, h -> {0, 27}|> *)
$\endgroup$
1
$\begingroup$

Here is an alternate solution which uses Lookup to establish the default value 0:

Union @@ Keys[{assoc1, assoc2}] // 
 AssociationThread[#, Transpose@Lookup[{assoc1, assoc2}, #, 0]] &
$\endgroup$

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.