I have a set of related functions that I use extensively in data work including keyValueMap
, which is an operator that lets you pass user defined functions to apply to Keys
, Values
or both.
apply g
to Values
:
keyValueMap[Key -> g_][as_Association] :=
AssociationThread[
KeyValueMap[List /* First][as] -> KeyValueMap[g][as]]
apply f
to Keys
:
keyValueMap[f_ -> Value][as_Association] :=
AssociationThread[
KeyValueMap[f][as] -> KeyValueMap[List /* Last][as]]
Apple f
to Keys
, g
to Values
:
keyValueMap[f_ -> g_][as_Association] :=
AssociationThread[KeyValueMap[f][as] -> KeyValueMap[g][as]]
Here Key
and Value
are just symbolic placeholders, slightly more mnemonic than using Identity
, (can Blank
be used instead?)
In your application, use:
dat[keyValueMap[Key -> List /* Reverse]] (* Normal *)
<|"a" -> {2, "a"}, "b" -> {"y", "b"}, "c" -> {{2, 3}, "c"}|>
or simply List
if order is not important.
To motivate the discussion, additional operators can be defined using keyValueMap
above. For example keySubKeyMap
with the following application:
Suppose the Values
are themselves nested Associations
. How to Map
a function combining upper level Keys
with those at lower level (hence Sub
)?
dat2 = Dataset[<|"a" -> <|2 -> 10|>, "b" -> <|"y" -> 11, "z" -> 12|>,
"c" -> <|2 -> 13, 3 -> 14|>|>]
Use:
keySubKeyMap[f_] :=
keyValueMap[
Key -> List /* Replace[{k_, as_} :> KeyMap[Curry[f, 2][k]][as]]]
Then:
dat2[keySubKeyMap[f]] // Normal
<|"a" -> <|f["a", 2] -> 10|>,
"b" -> <|f["b", "y"] -> 11, f["b", "z"] -> 12|>,
"c" -> <|f["c", 2] -> 13, f["c", 3] -> 14|>|>
KeyValueMap[#->{#2,#}&]@dat
? $\endgroup$Association@@(KeyValueMap[#->{#2,#}&]@dat)
? $\endgroup$Query
hack to resolve this. Now it seems not easy to achieve it in theQuery
way. $\endgroup$"c"->{{2, 3}, "c"}
$\endgroup$