Start learning free

LESSON 238 OF 671 · SETS

Removing From a Set in Go: delete and range

Lesson Read the full explanation

TL ; DR:

delete(s, x) takes x out of a map used as a set. A for loop with range visits every key once, in no fixed order.


colors := map[string]bool{"red": true, "blue": true, "green": true}

delete(colors, "blue")
delete(colors, "pink")          // not in it, nothing happens

for color := range colors {
    fmt.Println(color)          // red and green, in any order
}


Full lesson:

In Go, a set is a map with bool values. delete(s, x) removes the key x from it. If x isn't there, nothing happens.

for x := range s visits each key of the map once. With one variable, range gives only the keys. That's all a set needs.

The order isn't fixed. Go even picks a different order on purpose, from one run to the next.

So loop over a set when the order doesn't matter. A total, a count and a check are fine.


Your task

In a word game, the set found holds the words a player found. The words "qqq" and "zzz" aren't allowed. Remove both from found.

The player never found "zzz", so removing it changes nothing.

Then add up the points. A word scores one point per letter. Loop over found and add each word's length to score.

The code already prints how many words are left, and the points.

Expected output:

4 words
14 points
STEP 1 OF 3
    Ctrl + Enter to check

    GO · SETS

    Removing From Sets in Go, explained

    delete takes a key out

    In Go a set is usually a map with bool values. The built-in delete(s, x) removes the key x from the map. If x isn't there, nothing happens and there is no error.

    colors := map[string]bool{"red": true, "blue": true, "green": true}
    
    delete(colors, "blue")
    delete(colors, "pink")          // not in it, nothing happens
    
    for color := range colors {
        fmt.Println(color)          // red and green, in any order
    }
    

    Setting colors["blue"] = false would not do the same job: the key would stay in the map and still count in len. Use delete to remove a value from a set.

    Looping over a set

    for x := range s visits each key once. With a single variable, range over a map gives only the keys, which is all a set has to offer.

    The visiting order is not fixed, and Go deliberately varies it from one run to the next. Loop over a set when the order doesn't matter: a total, a count or a check gives the same answer in any order.

    Deleting while you loop is a related question. Go allows delete inside a range loop over the same map, and a key removed before the loop reaches it is not visited. In this lesson the two steps are kept apart anyway: first the unwanted words are removed, then the loop adds up what is left. That order also makes the final count easy to check by eye.

    It also helps to know how little delete returns. It gives back nothing, so there is no value to test to learn whether the key was present. If you need to know, look first with the comma-ok form (_, ok := found[word]) and then delete.

    The lesson's task

    The set found holds the words a player found. The words "qqq" and "zzz" aren't allowed, so both must be removed. The player never found "zzz", so removing it changes nothing. Then each remaining word scores one point per letter, and the loop adds up the points.

    1. Call delete(found, "qqq") and delete(found, "zzz").
    2. Below score := 0, write for word := range found, keeping only the key.
    3. Inside, add len(word) to score.
    func mainFunction() {
        words := []string{"cat", "tree", "sun", "qqq", "moon"}
        found := map[string]bool{}
        for _, word := range words {
            found[word] = true
        }
    
        delete(found, "qqq")
        delete(found, "zzz")
        fmt.Println(len(found), "words")
    
        score := 0
        for word := range found {
            score += len(word)
        }
        fmt.Println(score, "points")
    }
    

    The output is:

    4 words
    14 points
    

    Five words went in and "qqq" came out, leaving four. The remaining words have 3, 4, 3 and 4 letters, which add up to 14 whatever order the loop visits them in.

    Common mistakes

    • Setting the key to false instead of deleting it. len would still count it, and ranging over the map would still visit it.
    • Worrying about deleting a missing key. It is safe; no check is needed first.
    • Relying on the loop order. Sums and counts are safe. Printing the words one by one can differ between runs.

    A last point on len: it counts keys, so after the two delete calls it reports 4, not 5 and not 3. The call for "zzz" removed nothing, which is why the count only dropped by one.

    Key takeaways

    • delete(s, x) removes a key and does nothing when it is absent.
    • for x := range s gives each element of the set once, in no fixed order.
    Keep going with Go500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free