Best way to handle nested Maps?

You may use Query.

Query[
  All, 
  All, 
  All, 
  <|#, "score" -> If[EvenQ@#["age"], "A-", "B+"]|> &
 ]@sampleStructure
{<|"grade" -> 11, 
  "students" -> {<|"name" -> "bill", "age" -> 15, "score" -> "B+"|>, 
                 <|"name" -> "susan", "age" -> 16, "score" -> "A-"|>}|>, 
<|"grade" -> 12, 
  "students" -> {<|"name" -> "manuel", "age" -> 16, "score" -> "A-"|>, 
                 <|"name" -> "morris", "age" -> 17, "score" -> "B+"|>, 
                 <|"name" -> "jackie", "age" -> 16, "score" -> "A-"|>}|>}

Hope this helps.


Map at Level 3:

Map[Append[#, If[EvenQ[Last@#], "score" -> "A-", "score" -> "B+"]] &, 
  sampleStructure, {3}] // Dataset

enter image description here


Because it is much easier to deal with non-nested associations, I strongly recommend you consider reorganizing the data set so it is not nested. Doing so will bring two benefits: conceptually simplicity (less debugging) and better performance.

In the case of your example, write the data set as

students = {
   <|"name" -> "bill", "age" -> 15, "grade" -> 11|>,
   <|"name" -> "susan", "age" -> 16, "grade" -> 11|>,
   <|"name" -> "manuel", "age" -> 16, "grade" -> 12|>,
   <|"name" -> "morris", "age" -> 17, "grade" -> 12|>,
   <|"name" -> "jackie", "age" -> 16, "grade" -> 12|>
   };

Then your task can be implemented by writing a simple function.

assignScore[student_] :=
  Module[{pupil = student}, 
    AppendTo[pupil, "score" -> If[EvenQ[pupil["age"]], "A-", "B+"]]]

and carried out by evaluating

students = assignScore /@ students;
students // Dataset

students

Further, with this organization, all kinds of queries become simple because they are intuitive.

Group the students by age.

GatherBy[students, #age &] // Dataset

by_age

Query for those students who earned an A-.

Query[Select[#score == "A-" &]]@students // Dataset

or

Dataset[students][Select[#score == "A-" &]]

Either of the above give

high_score

In conclusion: the best way to handle nested maps of associations is to avoid them.