# Change a list of associations by applying a function to specific keys?

If I have a list of associations (listAssoc) with members all having key someKey, how can I generate a new list of associations listAssoc2 that is equal to listAssoc except the values of someKey have all been changed by having some function f applied to their values?

MapAt[Sin, #, "somekey"] & /@ listAssoc

• If you modify the third argument of MapAt then you won't need to map a pure function: MapAt[f, ascList, {All, Key[someKey]}] Dec 30, 2019 at 19:27

You can also use Query. Using a variation of @kglr's example:

ascList = Table[
<|a->RandomInteger[100], "someKey"->RandomInteger[100], c->RandomInteger[100]|>,
5
]


{<|a -> 32, "someKey" -> 16, c -> 90|>, <|a -> 77, "someKey" -> 28, c -> 82|>, <|a -> 39, "someKey" -> 70, c -> 66|>, <|a -> 21, "someKey" -> 79, c -> 32|>, <|a -> 66, "someKey" -> 16, c -> 4|>}

Then:

Query[{"someKey" -> foo}] /@ ascList


{<|a -> 32, "someKey" -> foo[16], c -> 90|>, <|a -> 77, "someKey" -> foo[28], c -> 82|>, <|a -> 39, "someKey" -> foo[70], c -> 66|>, <|a -> 21, "someKey" -> foo[79], c -> 32|>, <|a -> 66, "someKey" -> foo[16], c -> 4|>}

In m_goldberg's deleted answer, he suggests a nice refinement:

Query[All, {"someKey" -> foo}] @ ascList


{<|a -> 88, "someKey" -> foo[78], c -> 98|>, <|a -> 2, "someKey" -> foo[18], c -> 24|>, <|a -> 52, "someKey" -> foo[8], c -> 64|>, <|a -> 7, "someKey" -> foo[96], c -> 73|>, <|a -> 92, "someKey" -> foo[75], c -> 49|>}

• @m_goldberg I liked your answer, so I included it. If you undelete your answer, I would be happy to remove my addition. Dec 30, 2019 at 18:26
ascList = Table[<|a -> RandomInteger[100], someKey -> RandomInteger[100],
c -> RandomInteger[100]|>, 5]


{<|a -> 44, someKey -> 93, c -> 67|>,
<|a -> 49, someKey -> 44, c -> 85|>,
<|a -> 61, someKey -> 4, c -> 88|>,
<|a -> 38, someKey -> 24, c -> 8|>,
<|a -> 78, someKey -> 87, c -> 44|>}

Normal @ Dataset[ascList][All, {Key[someKey] -> foo}]


{<|a -> 44, someKey -> foo[93], c -> 67|>,
<|a -> 49, someKey -> foo[44], c -> 85|>,
<|a -> 61, someKey -> foo[4], c -> 88|>,
<|a -> 38, someKey -> foo[24], c -> 8|>,
<|a -> 78, someKey -> foo[87], c -> 44|>}

Also

MapIndexed[If[#2[[2, 1]] === someKey, foo@#, #] &, ascList, {2}]


same result

MapIndexed[If[#2[[1, 1]] === someKey, foo@#, #] &] /@ ascList


same result

Use Part assignment:

listAssoc2 = listAssoc;
listAssoc2[[All, Key[someKey]]] = f /@ listAssoc2[[All, Key[someKey]]]


Since V 13.1 we can also use ReplaceAt. To demonstrate its usefulness I create a list with a missing value:

  list =
{<|"a" -> 32, "b" -> 16, "c" -> 90|>,
<|"a" -> 77, "b" -> Missing[], "c" -> 82|>,
<|"a" -> 39, "b" -> 70, "c" -> 66|>,
<|"a" -> 21, "b" -> 79, "c" -> 32|>,
<|"a" -> 66, "b" -> 16, "c" -> 4|>};

ReplaceAt[x_?NumberQ :> x + 10, {All, "b"}] @ list // Dataset


To get the same result with the "classical" Query - method we would have to write:

Query[All, <|#, "b" -> If[NumberQ[#b], #b + 10, Missing[]]|> &] @ list // Dataset


Additional Conditions can be injected easily:

ReplaceAt[x_?NumberQ /; Between[x, {1, 30}] :> x + 10, {All, "b"}] @ list