Start learning free

LESSON 125 OF 667 · DICTIONARIES

Checking for a Key in a C++ unordered_map

Lesson Read the full explanation

TL ; DR:

Call m.count(key) to ask whether an unordered_map has a key. It returns 1 when the key is there and 0 when it isn't.


unordered_map<string, string> capitals = {{"France", "Paris"}, {"Japan", "Tokyo"}};

if (capitals.count("Japan") > 0) {
    cout << capitals["Japan"] << endl;   // Tokyo
}

if (capitals.count("Spain") == 0) {
    cout << "No Spain" << endl;          // No Spain
}


Full lesson:

A map has each key at most once. So count can only be 1 or 0.

capitals.count("Spain") > 0 is true when "Spain" is a key. == 0 asks the opposite.

Don't check with capitals["Spain"]. On a missing key, [] adds the key, with an empty value.

Newer C++ also has a contains method. This course uses C++17, which doesn't have it. So use count.

A value is not a key

count looks only at the keys. capitals.count("Paris") is 0, because "Paris" is a value.

A key must match exactly, upper and lower case too. capitals.count("japan") is 0.


Your task

In pets, each key is a pet's name, and its value is the pet's kind.

First, check whether "Tom" is a key of pets. If it is, print Tom is a followed by Tom's kind.

Then check that "cat" is not a key, with count. If so, print cat is not a key.

"cat" is in pets, but only as a value. It is Tom's kind.

Expected output:

Tom is a cat
cat is not a key
STEP 1 OF 2
    Ctrl + Enter to check

    C++ · DICTIONARIES

    Dictionary Key Check in C++, explained

    Asking whether a key is there

    An unordered_map stores keys with values. Before you use a key, you often need to know whether the map has it. The method for that is count(key). A map holds each key at most once, so count returns only two answers: 1 when the key is there, and 0 when it isn't.

    unordered_map<string, string> capitals = {{"France", "Paris"}, {"Japan", "Tokyo"}};
    if (capitals.count("Japan") > 0) {
        cout << capitals["Japan"] << endl;   // Tokyo
    }
    if (capitals.count("Spain") == 0) {
        cout << "No Spain" << endl;          // No Spain
    }
    

    Use count(key) > 0 for "the key exists" and count(key) == 0 for "the key is missing". Newer C++ versions also have a contains method, but C++17, which this course uses, does not, so write it with count.

    Do not check with []

    The square brackets look like a natural way to test, but they change the map. Reading capitals["Spain"] on a missing key adds "Spain" with an empty string as its value. The map then has three entries, and capitals.count("Spain") is 1. For an unordered_map<string, int>, the added value is 0.

    So always ask with count first, and read with [] only inside the check.

    Keys only

    • A value is not a key. capitals.count("Paris") is 0, because "Paris" is a value. count looks only at keys.
    • Exact match. Upper and lower case count as different letters, so capitals.count("japan") is 0.
    • Not an error. Asking about a missing key just returns 0. Nothing crashes and nothing is added.

    The exercise: pets and kinds

    The map pets goes from a pet's name to its kind: Rex is a dog, Tom is a cat and Polly is a parrot. The task has two checks:

    1. If pets.count("Tom") is greater than 0, print Tom is a followed by pets["Tom"]. Reading with [] is safe here because the check just proved the key exists.
    2. If pets.count("cat") is 0, print cat is not a key. The word "cat" does appear in the map, but only as Tom's kind, which is a value. So the count is 0.
    unordered_map<string, string> pets = {{"Rex", "dog"}, {"Tom", "cat"}, {"Polly", "parrot"}};
    
    if (pets.count("Tom") > 0) {
        cout << "Tom is a " << pets["Tom"] << endl;
    }
    if (pets.count("cat") == 0) {
        cout << "cat is not a key" << endl;
    }
    

    The output is:

    Tom is a cat
    cat is not a key
    

    Notice the space at the end of "Tom is a ". Without it, the kind would run into the word before it.

    Two ways to get it wrong

    Suppose you wrote the first check as if (pets["Tom"] != ""). For Tom it works, but for a name that is not in the map it would add that name as a new key with an empty kind, and the map would grow without any warning. The second slip is searching for a value as if it were a key. If you want to know whether any pet is a cat, count("cat") cannot tell you, because it only looks at the names.

    Both mistakes come from forgetting what a map is for: you look something up by key, and the key must be exactly the one you stored.

    Key takeaways

    • m.count(key) is 1 when the key is there and 0 when it isn't.
    • count checks keys only, and the match is exact.
    • Never test with m[key]: on a missing key, it adds the key.
    • Read m[key] only after count has said the key exists.
    Keep going with C++500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free