3
$\begingroup$

Here is a simplified version of my problem.

I have a nested Association.

worksheet = <|"startDate" -> 
   DateObject[{2017, 8, 10}, "Day", "Gregorian", -5.`], 
  "eventList" -> {
    <|"eventName" -> "Thursday Stratified 49r Pairs", 
     "eventTotal" -> 336.`|>,
    <|"eventName" -> "Thursday Aftt Side Pairs",
      "eventTotal" -> 240.`|>}|>

Below are the Keys

Keys[worksheet]
(* {"startDate", "eventList"} *)

I have a function to fix the names in the eventList when they are bad. Simplified function is:

fixName[name_] := Module[
  {
   newName = name
   },
  newName = StringReplace[newName, "Aftt" -> "Aft"]
  ]

Below is the input name and the corrected name for the second entry in eventList

worksheet["eventList"][[2]]["eventName"]
(* "Thursday Aftt Side Pairs" *)

fixName[worksheet["eventList"][[2]]["eventName"]]
(* "Thursday Aft Side Pairs" *)

I want to Scan the names in eventList and replace the corrected name with the input name.

I want to replace worksheet with the edited version.

Here is what I tried:

worksheet = Function[wsIn,
  Module[
   {
    len = Length[wsIn["eventList"]],
    wsOut = wsIn
    },
   Scan[
    (wsOut["eventList"][[#]]["eventName"] = 
       fixName[wsOut["eventList"][[#]]["eventName"]]) &,
    Range[len]
    ];
   wsOut
   ]
  ][worksheet]

However, this produces an error

Association::setps: <|eventName->Thursday Stratified 49r Pairs,
                     eventTotal->336.|> in the part assignment
is not a symbol.

Need help with this code.

$\endgroup$
  • $\begingroup$ Unless you have a specific reason to do otherwise, it is typically easier to just return a modified object instead of trying to do in-place modifications. For instance, this should work in for the case at hand, while being significantly more readable: Query["eventList", All, "eventName", fixName]@worksheet $\endgroup$ – Lukas Lang Aug 7 at 22:04
  • $\begingroup$ Why not use ReplacePart? You can also use wsOut[["eventList", #, "eventName"]] = ... but that'll be less efficient $\endgroup$ – b3m2a1 Aug 7 at 22:04
  • 1
    $\begingroup$ @LukasLang it's not even really an in-place modification since worksheet isn't held on input. $\endgroup$ – b3m2a1 Aug 7 at 22:04
  • $\begingroup$ how about fiXName[key_,repl_]:= Replace[#,<|key -> v_, y___|> :><|key -> StringReplace[v, repl],y|> ,All]&; fiXName["eventName", "Aftt" -> "Aft"]@worksheet? $\endgroup$ – kglr Aug 8 at 1:30
4
$\begingroup$

Use AssociateTo to modify the inner association in the worksheet, i.e.:

Function[wsIn,
  Module[{len = Length[wsIn["eventList"]], wsOut = wsIn},
   Scan[
    AssociateTo[
      wsOut["eventList"][[#]], 
      "eventName" -> fixName[wsOut["eventList"][[#]]["eventName"]]
      ] &,
    Range[len]];
   wsOut]
  ][worksheet]
$\endgroup$
  • $\begingroup$ AssociateTo is exactly what I needed. Thank you sakra. $\endgroup$ – Jack LaVigne Aug 9 at 1:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.