6. Nested

Maps can contain maps, creating a nested structure. For example:

map[string]map[string]int
map[rune]map[string]int
map[int]map[string]map[string]int

Assignment

Because Textio is a glorified customer database, we have a lot of internal logic for sorting and dealing with customer names.

Complete the getNameCounts function. It takes a slice of strings names and returns a nested map. The parent map's keys are all the unique first characters (see https://go.dev/blog/strings) of the names, the nested maps keys are all the names themselves, and the value is the count of each name.

For example:

billy
billy
bob
joe

Creates the following nested map:

b: {
    billy: 2,
    bob: 1
},
j: {
    joe: 1
}
circle-info
  • The test suite is not printing the map you're returning directly, but instead checking a few specific keys.

  • You can convert a string into a slice of runes as follows:

Solution

You need to:

1

Group names by their first letter

Use a map keyed by rune (the first character) whose values are maps from the full name to counts.

2

Count how many times each name appears

Increment the nested map's count for each name encountered.

3

Return a nested map structure

Return map[rune]map[string]int with counts grouped by first rune.

Breaking It Down

Step 1: Create the Outer Map

This creates the structure:

Step 2: Loop Through Names

Step 3: Get the First Character

This converts the string to a slice of runes and gets the first one.

Example:

  • "billy" β†’ []rune{'b', 'i', 'l', 'l', 'y'} β†’ first is 'b'

Step 4: Check If Inner Map Exists

Before you can increment a count, you need to make sure the inner map exists:

If the inner map doesn't exist yet, create it.

Step 5: Increment the Count

This increments the count for that specific name.

Complete Solution (again for convenience)

Step-by-Step Trace

Let's trace through with:

1

Start

2

Iteration 1: name = "billy"

3

Iteration 2: name = "billy"

4

Iteration 3: name = "bob"

5

Iteration 4: name = "joe"

Final result:

Why Check if result[firstChar] == nil?

When you access a map key that doesn't exist:

You can't index a nil map:

So you must create the inner map first:

Alternative: Check with Two-Value Lookup

You could also write it like this:

Both approaches work. The == nil check is simpler for maps.

Key Takeaway

When working with nested maps, always check if the inner map exists before trying to use it: