BYU logo Computer Science

To start this guide, download this zip file.

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

Getting key/value pairs from a dictionary

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

food = 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:

food = 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.

Here are these ideas put into a program, which is in meals.py:

if __name__ == '__main__':
    meals = {
        'breakfast': 'yogurt, granola, and fruit',
        'lunch': 'Cupbop',
        'dinner': 'lasagna and salad'
    }
    food = meals['dinner']
    print(f"I had {food} for dinner.")
    food = meals.get('brunch', 'buttered toast and apple juice')
    print(f"I had {food} for brunch.")

If you run this program, you get:

I had lasagna and salad for dinner.
I had buttered toast and apple juice for brunch.

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}. ๐Ÿ˜‹')

The file all_meals.py has this short program:

if __name__ == '__main__':
    meals = {
        'breakfast': 'yogurt, granola, and fruit',
        'lunch': 'Cupbop',
        'dinner': 'lasagna and salad'
    }
    for meal, description in meals.items():
        print(f'For {meal} we are serving {description}. ๐Ÿ˜‹')

If you run it, 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. ๐Ÿ˜‹

To understand what items() is doing, it uses your dictionary, gets all of the key/value pairs, and returns a sequence 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')]

Checking whether a key is in a dictionary

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

if 'dinner' in meals:
    print("Yay, we are eating dinner.")
if 'brunch' in meals:
    print("Yay, we are eating brunch.")

will print

print("Yay, we are eating dinner.")

Here is another example, which is in home_towns.py:

if __name__ == '__main__':
    hometowns = {
        'Dallin Oaks': 'Provo, UT',
        'Jeffery Holland': 'St George, UT',
        'Merril Bateman': 'Lehi, UT',
        'Cecil Samuelson': 'Salt Lake City, UT',
        'Kevin Worthen': 'Dragerton, UT',
        'Shane Reese': 'Logan, UT'
    }
    for person in ['Kevin Worthen', 'Henry Eyring', 'Shane Reese', 'Ernest Wilkinson', 'Karl Maeser']:
        if person in hometowns:
            print(f'{person} was born in {hometowns[person]}.')
        else:
            print(f"I don't know where {person} was born.")

Here the dictionary maps Presidents of BYU to the place they were born. If you run this code you will see:

Kevin Worthen was born in Dragerton, UT.
I don't know where Henry Eyring was born.
Shane Reese was born in Logan, UT.
I don't know where Ernest Wilkinson was born.
I don't know where Karl Maeser was born.

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). We have given you starter code in emojis.py:

import sys


def add_emojis(text: str, emojis: dict[str, str]) -> str:
    """Replace words in `emojis` with their corresponding symbols."""
    # Write code here
    pass


if __name__ == '__main__':
    emojis = {
        'dog': '๐Ÿถ',
        'puppy': '๐Ÿถ',
        'dogs': '๐Ÿถ๐Ÿถ',
        'cat': '๐Ÿฑ',
        'tree': '๐ŸŒณ',
        'bird': '๐Ÿฆ'
    }
    print(add_emojis(sys.argv[1], emojis))

work with a friend to solve this problem

Here is a solution:

def add_emojis(text: str, emojis: dict[str, str]) -> str:
    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 the code

python emojis.py "The dog chased the cat which chased the bird that sat in the tree in my yard."

We get:

The ๐Ÿถ chased the ๐Ÿฑ which chased the ๐Ÿฆ that sat in the ๐ŸŒณ in my yard.

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: dict[str, int], teams_by_age: dict[str, int]) -> list[tuple[str, str]]:
    """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โ€.

There is starter code in assign_teams.py:

def assign_teams(participants: dict[str, int], teams_by_age: dict[str, int]) -> list[tuple[str, str]]:
    """Return a list of (person, team) tuples"""
    # Write code here
    pass


def print_teams(teams: list[tuple[str, str]]):
    for player, team in teams:
        print(f'{player} is on team {team}')


def main(participants, age_groups):
    teams = assign_teams(participants, age_groups)
    print_teams(teams)


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

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

    main(participants, age_groups)

work with a friend to solve this problem

Here is code to do this:

def assign_teams(participants: dict[str, int], teams_by_age: dict[str, int]) -> list[tuple[str, str]]:
    # 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
  • go through all the participants, which are tuples of (name, age)
  • find the nearest age group for the participant
  • get the team for that age group
  • create a new tuple of (name, team) and append to a list of tuples
  • return all the tuples

If we run the code, then we get:

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

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: dict[str, str], message: str) -> str:
    """Return the encoded message using the codex to map letters."""

You have some starter code in encode.py:

import sys


def encode(codex: dict[str, str], message: str) -> str:
    """Return the encoded message using the codex to map letters."""
    # Write code here
    pass


def main(message, codex):
    encoded = encode(codex, message)
    print(encoded)


if __name__ == '__main__':
    simple_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'
    }
    main(sys.argv[1], simple_codex)

This works the same way as the emoji problem above! You just have to be sure to worry about case.

work with a friend to solve this problem

Here is one way to solve this problem:

def encode(codex: dict[str, str], message: str) -> str:
    # 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 run the completed code:

python encode.py "I like fish."

we get:

A jakg sawr.