# Mapping over an association producing an unexpected result

The documentation for associations says that the keys of an association are transparent for many operations. Map is one such operation. However, I am confronted with something a bit unexpected.

Clear[a, f];

a = <|1 -> <|2 -> {{6, 8}, {6, 10}}|>, 6 -> <|8 -> {{14, 18}, {2, 4}}|>|>;

f = Select[#[[2]] >= 10 &] @ # &;

f /@ a (* <|1 -> <| |>, 6 -> <| |>|> *)

f @ {{6, 8}, {6, 10}} (* {{6, 10}} *)

f @ {{14, 18}, {2, 4}} (* {{14, 18}} *)


I don't understand why f applied individually to the arguments produces the desired result, but when mapped over those same arguments inside the association, does not. What is the error in my thinking?

First, your construction of f is a bit malformed. You are using the operator form of Select, therefore the Select expression itself acts as a function; you do not need to add @# & to it. Use instead:

f = Select[#[[2]] >= 10 &];


The reason that your operations are not the same can be seen by mapping a dummy function foo:

foo /@ a

<|1 -> foo[<|2 -> {{6, 8}, {6, 10}}|>], 6 -> foo[<|8 -> {{14, 18}, {2, 4}}|>]|>


Because you have nested Assocations in a the function is applied to an Association rather than a List as I think you expect. We can see that simple function application does not "go inside" Association:

foo[<|2 -> {{6, 8}, {6, 10}}|>]

foo[<|2 -> {{6, 8}, {6, 10}}|>]


Depending on what you want you may be able to write simply:

Map[f] /@ a

<|1 -> <|2 -> {{6, 10}}|>, 6 -> <|8 -> {{14, 18}}|>|>


However if you want this selection to work on arbitrarily nested Associations you will need something else. One solution is this abstraction that threads a function over Association expressions:

(p : valueMap[fn_])[a_Association] := p /@ a
valueMap[fn_][other_]              := fn @ other


Now:

a2 = Append[a, 7 -> {{10, 20}, {1, 2}}];

a2 // valueMap[f]

<|1 -> <|2 -> {{6, 10}}|>, 6 -> <|8 -> {{14, 18}}|>, 7 -> {{10, 20}}|>

• Thank you for the excellent answer. Commented Sep 15, 2014 at 7:30
• @Shredderroy You're welcome. I added an abstraction (valueMap) that simplifies the application to arbitrarily nested Associations. Commented Sep 15, 2014 at 7:39