BYU logo Computer Science

Dictionaries

A dictionary is a map of keys to values. For example, this dictionary maps a key that is a meal to a value that is a string describing that meal:

meals = {
    'breakfast': 'yogurt, granola, and fruit',
    'lunch': 'Cupbop',
    'dinner': 'lasagna and salad'
}

a dictionary of meals with three key/value pairs (1) breakfast : yogurt, granola and fruit, (2) lunch : Cupbop, (3) dinner : lasagna and salad

The purpose of the dictionary is to be able to store and look up key/value pairs. The dictionary above lets us store what we ate today and then to perform calculations on it.

This is similar to what meal tracking or fitness tracking apps do! The screenshot below shows how a meal tracking app stores a list of items along with their nutrition information for each meal. We will eventually show you how to store more complex information in a dictionary.

picture of a meal tracking app, showing tracking meals each day and using this data to create charts and graphs

Basic operations

Here are a few of the basic things you can do with a dictionary

Create an empty dictionary

You can create a dictionary using the curly brackets notation shown above. This is an empty dictionary:

meals = {}

Add key/value pairs to a dictionary

You can add key/value pairs to the dictionary one at a time using square brackets:

meals['second lunch'] = 'crackers and cheese'

Dictionaries cannot have duplicate keys

This will over-write the value of the ‘lunch’ key:

meals['lunch'] = 'peanut butter and jelly sandwich'

The dictionary will now hold these key/value pairs:

{
    'breakfast': 'yogurt, granola, and fruit',
    'lunch': 'Cupbop',
    'dinner': 'lasagna and salad',
}

Get key/value pairs from a dictionary

You can retrieve the value for a key also using square brackets:

print(meals['dinner'])

If you try to retrieve a key that is not present, you will get an error. For example, asking for meals['brunch'] with the above example cause an error:

KeyError: 'brunch'

You can also use the get() function:

result = meals.get('brunch', 'buttered toast and apple juice')

This tells Python to look for brunch in the meals dictionary and return the value. But if that key doesn’t exist, then return buttered toast and apple juice instead.

Iterate over the key/value pairs in a dictionary

You can iterate over all of the keys and values using for ... in and items():

for meal, description in meals.items():
    print(f'For {meal} we are serving {description}. 😋')

This will print:

For breakfast we are serving yogurt, granola, and fruit. 😋
For lunch we are serving Cupbop. 😋
For dinner we are serving lasagna and sald. 😋

When you call items() you get an object that has a list of key/value tuples. You can turn this into a list:

print(list(meals.items()))

This will print:

[('breakfast', 'yogurt, granola, and fruit'), ('lunch', 'Cupbop'), ('dinner', 'lasagna and sald')]

Types of keys

You can use numbers as the keys for a dictionary. For example, this dictionary maps a number to a description of whether that number has any useful properties:

significance = {
    7: 'prime',
    2: 'even prime',
    3: 'prime',
    5: 'prime',
    9: 'square',
    4: 'even square',
    1: 'multiplicative identity'
}

Then we can print an entry using:

print(significance[5])

Checking whether a key is in a dictionary

You can check whether a key is in a dictionary using in. For example:

print('dinner' in meals)
print('brunch' in meals)

will print

True
False

Likewise, using our significance dictionary above:

for number in range(10):
    if number in significance:
        print(f'{number} is {significance[number]}.')
    else:
        print(f"I don't know anything special about {number}.")

This will print:

I don't know anything special about 0.
1 is multiplicative identity.
2 is even prime.
3 is prime.
4 is even square.
5 is prime.
I don't know anything special about 6.
7 is prime.
I don't know anything special about 8.
9 is even square.

Example: replacing words with emojis

The world can always use more emojis! You are given a dictionary mapping words to emojis. For example:

emojis = {'dog': '🐶', 'cat': '🐱', 'tree': '🌳', 'bird': '🐦'}

Your goal is to replace all instances of a word in a string with it’s corresponding emoji. You need to ignore the case of the word.

Using the dictionary above, the string 'My dog has fleas' becomes 'My 🐶 has fleas'.

Write a function to do this, add_emojis(text, emojis), and the function should return a new string.

Here is a function to do this:

def add_emojis(text, emojis):
    new_words = []
    # split the text into words
    for word in text.split():
        # check if this word is in the dictionary as a key
        if word in emojis:
            # get the emoji from the dictionary that corresponds to this word
            word = emojis[word]
        # append either the original word or the emoji to the list of words
        new_words.append(word)
    # combine the new words into a string, with spaces between them, and return that string
    return " ".join(new_words)
  • We use split() to split the string into a set of words
  • We use if word in emojis to check if the dictionary has a key for a given word
  • We use emojis[word] to get the emoji for a given word
  • We use join() to turn a list of words back into a string, with each word separated by spaces

If we run this code:

emojis = {
    'dog': '🐶',
    'cat': '🐱',
    'tree': '🌳',
    'bird': '🐦'
}

result = add_emojis("The dog chased the cat which chased the bird that sat in the tree in my yard.", emojis)
print(result)

We get:

The 🐶 chased the 🐱 which chased the 🐦 that sat in the 🌳 in my yard.

Example: team assignments

Let’s imagine you want to write a small program to help community members register for sports teams at the local recreation center. You have a dictionary that maps age groups to team names:

teams_by_age = {
    0: 'Team Toddlers',
    3: 'Tiny Troupers',
    6: 'Starting Stars',
    9: 'Mighty Middles',
    12: 'Too Cool',
    15: 'Boundless'
}

You also have a list of participants and their ages:

participants = [
    ('Joe', 14),
    ('Jane', 6),
    ('Johnny', 4),
    ('Jennifer', 20),
    ('Jack', 16),
    ('Janice', 2)
]

You want to assign each participant to a team based on their age:

def assign_teams(participants, teams_by_age):
    """Returns a list of tuples of name and team."""

This function should return a list of tuples that list person name and team such as (‘Joe’,‘Too Cool’).

To figure out which team a person is assigned to, find the nearest multiple of 3 that is less than or equal to the participant age. You can do this with:

nearest_multiple = (age // 3) * 3

If the participant does not have an age-group assignment, their team is “Adult League”.

Here is code to do this:

def assign_teams(participants, teams_by_age):
    # make a list of tuples (person, team)
    result = []
    # loop through all the tuples of (name, age)
    for name, age in participants:
        # compute the group for this age (nearest multiple of 3)
        age_group = (age // 3) * 3
        # loop up the team name for this age group, and if none, then the team is 'Adult League'
        team_name = teams_by_age.get(age_group, "Adult League")
        # append a tuple of (name, group) to the list of tuples
        result.append((name, team_name))
    return result

If we start with the two dictionaries above and then:

print(assign_teams(participants, teams_by_age))

we get:

[('Joe', 'Too Cool'), ('Jane', 'Starting Stars'), ('Johnny', 'Tiny Troupers'), ('Jennifer', 'Adult League'), ('Jack', 'Boundless'), ('Janice', 'Team Toddlers')]

Example — cipher

You are given a codex, which is a dictionary mapping letters to their “encoded” letter. Your job is to use this codex to encode a message.

For example, if the codex maps d -> x, o -> p, and g -> e, then dog is encoded as xpe. This is the most simple way of encoding messages and is really easy for a computer to break, but it is usually the starting point to discuss the concept of encryption.

The codex only contains lowercase letters, but you should encode uppercase letters also. Be sure to preserve casing.

Here is an example of a codex:

codex = {
 'a': 'd',
 'b': 'e',
 'c': 'z',
 'd': 'h',
 'e': 'g',
 'f': 's',
 'g': 'n',
 'h': 'r',
 'i': 'a',
 'j': 'b',
 'k': 'k',
 'l': 'j',
 'm': 'c',
 'n': 'u',
 'o': 'y',
 'p': 't',
 'q': 'q',
 'r': 'x',
 's': 'w',
 't': 'v',
 'u': 'p',
 'v': 'f',
 'w': 'i',
 'x': 'l',
 'y': 'm',
 'z': 'o'
}

Here is the function to write:

def encode(codex, message):
    """Return the encoded message using the codex to map letters."""

This works the same way as the emoji problem above! We just have to be sure to worry about case. Here is one way to solve this problem:

def encode(codex, message):
    # accumulate a new string
    result = ""
    # loop through all of the characters in the message
    for char in message:
        # start out with the new character being the same as the old one
        new_char = char
        # check if the lowercase version of the character is in the codex
        if char.lower() in codex:
            # get the encoded character from the codex
            new_char = codex[char.lower()]
        if char.isupper():
            # if the character was originally uppercase, be sure the new character is also uppercase
            new_char = new_char.upper()

        # note, any punctuation is left alone because it won't be in the codex!

        # append the encoded character in the string
        result += new_char
    return result

If we use the codex above and then run:

print(encode(codex, 'I like fish.'))

we get:

A jakg sawr.