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$
4
  • $\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, 2019 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, 2019 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, 2019 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, 2019 at 1:30

1 Answer 1

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$
1
  • $\begingroup$ AssociateTo is exactly what I needed. Thank you sakra. $\endgroup$ Aug 9, 2019 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.