Counting words is the classic first use of a map: the word is the key and the
number of occurrences is the value. Along the way you will meet the strings
package and the map’s convenient zero value.
Statement
Write a function countWords(text string) map[string]int that returns how many
times each word appears in text. Split the text on whitespace and compare
words case-insensitively.
Constraints:
- The signature must be
func countWords(text string) map[string]int. - Split on any run of whitespace, ignoring extra spaces.
- Treat
Go,goandGOas the same word (lower case them).
Example
For the text "the cat sat on the mat", the counts are:
cat: 1
mat: 1
on: 1
sat: 1
the: 2
Map iteration order is random in Go, so the lines above are shown sorted for readability.
Starter code
package main
import (
"fmt"
"strings"
)
// countWords returns how many times each word appears in text.
func countWords(text string) map[string]int {
counts := make(map[string]int)
// Split text into words and count them.
return counts
}
func main() {
counts := countWords("the cat sat on the mat")
fmt.Println(counts)
}
Hints
Hint 1
strings.Fields splits on any run of whitespace and drops empty pieces, which
is exactly what you want here.
Hint 2
strings.ToLower(text) before splitting makes the count case-insensitive.
Hint 3
counts[word]++ works even the first time you see a word: reading a missing key
returns the zero value 0, and ++ turns it into 1.
Solution
Show the solution
package main
import (
"fmt"
"sort"
"strings"
)
func countWords(text string) map[string]int {
counts := make(map[string]int)
for _, word := range strings.Fields(strings.ToLower(text)) {
counts[word]++
}
return counts
}
func main() {
counts := countWords("the cat sat on the mat")
words := make([]string, 0, len(counts))
for word := range counts {
words = append(words, word)
}
sort.Strings(words)
for _, word := range words {
fmt.Printf("%s: %d\n", word, counts[word])
}
}strings.ToLower normalises the case so The and the count together.
strings.Fields splits the text on whitespace and skips empty entries, so extra
spaces cause no trouble. The map starts empty, and counts[word]++ relies on
the fact that a missing key reads back as 0, so the first sighting becomes 1
and every repeat adds one. Because a map has no guaranteed order, main sorts
the keys before printing.
Common mistakes:
- Using
strings.Split(text, " "), which keeps empty strings when there are double spaces.strings.Fieldsavoids that. - Forgetting to lower-case, so
Goandgoare counted as different words. - Assuming a fixed print order. Map iteration order is randomised on purpose; sort the keys if order matters.
Maps are the key data structure here. Learn them thoroughly in Maps in Go.