Drills

Drills — write the functions

Reading about maps isn't enough — you have to write. Five tasks, easy to harder. For each, write the function, run it on the examples, then compare with the solution. Try it yourself first.

1 (easy) — tally. Count how many times each word appears.

tally([]string{"a", "b", "a"}) → map[a:2 b:1]
func tally(words []string) map[string]int {
    counts := make(map[string]int)
    for _, w := range words {
        counts[w]++
    }
    return counts
}

2 (easy) — distinct. How many unique values are in the slice? (A map used as a set: only the keys matter.)

distinct([]string{"a", "b", "a"}) → 2
func distinct(xs []string) int {
    seen := make(map[string]bool)
    for _, x := range xs {
        seen[x] = true
    }
    return len(seen)
}

3 (medium) — merge. Add two count-maps together into a new one.

merge(map[string]int{"a": 1}, map[string]int{"a": 2, "b": 5}) → map[a:3 b:5]
func merge(a, b map[string]int) map[string]int {
    out := make(map[string]int)
    for k, v := range a {
        out[k] += v
    }
    for k, v := range b {
        out[k] += v
    }
    return out
}

4 (medium) — maxKey. Return the key with the largest value (assume no ties).

maxKey(map[string]int{"x": 1, "y": 9, "z": 3}) → "y"
func maxKey(m map[string]int) string {
    best := ""
    bestN := -1
    for k, v := range m {
        if v > bestN {
            best, bestN = k, v
        }
    }
    return best
}

Why "no ties"? Because range order is random — with two equal top values, you'd get either key, unpredictably. That ambiguity is exactly the random-order gotcha biting in miniature.

5 (harder) — groupByLen. Group words by their length: a map[int][]string (the values are slices).

groupByLen([]string{"go", "cat", "hi", "dog"}) → map[2:[go hi] 3:[cat dog]]
func groupByLen(words []string) map[int][]string {
    out := make(map[int][]string)
    for _, w := range words {
        out[len(w)] = append(out[len(w)], w)
    }
    return out
}

append to a missing key just works: the zero value of a slice is nil, and appending to nil starts a new slice. Maps and slices fit together neatly.

Tip. Call each from main and check against the examples. These pure functions — a slice in, a map out — are exactly what we'll pin down with go test in lesson 13.