Coiteration¶

🎨 tuple¶

https://english.stackexchange.com/questions/12980/how-to-pronounce-tuple

In [ ]:
info = ('Bean', 'Professor', 'Computer Science', 'BYU')
info
In [ ]:
type(info)

NOTES

  • A tuple is a collection of information
  • You define one with parenthesis and commas
In [ ]:
info
In [ ]:
info.append('Provo')

🖌 Unpacking¶

In [ ]:
info
In [ ]:
name, job, department, university = info

print(f'{job} {name} works in the {department} department at {university}.')
In [ ]:
info
In [ ]:
name, job = info

NOTES

  • The "expected" count refers to the number of variables, not to the size of the contents

🖌 Return Multiple Values¶

In [ ]:
def sorted_order(a, b):
    """Return a and b in ascending order"""
    if a < b:
        return (a, b)
    else:
        return (b, a)

NOTES

  • Often, the () are left off of a typle literal when you are returning or assigning values
In [ ]:
first, second = sorted_order(4, 2)
print(f'First comes {first}, then comes {second}')
In [ ]:
first, second = sorted_order(1, 3)
print(f'First comes {first}, then comes {second}')
In [ ]:
def smallest_word(words):
    """Return the smallest word along with its length"""
    smallest = None
    for word in words:
        if smallest is None or len(word) < len(smallest):
            smallest = word
    return smallest, len(smallest)
In [ ]:
word, size = smallest_word(['apple', 'iron', 'cat', 'pigeon'])
print(f'The smallest word is {word} (of length {size})')

🎨 zip¶

In [ ]:
names = ['John', 'Juan', 'João', 'Giovanni']
ages = [23, 18, 24, 22]

for name, age in zip(names, ages):
    print(f'{name} is {age} years old')

NOTES

  • draw out the lists
  • Show the pairings
  • zip creates tuples by pairing items in lists
In [ ]:
names = ['John', 'Juan', 'João', 'Giovanni']
ages = [23, 18, 24, 22]
majors = ['Chemistry', 'Animation', 'Sociology', 'Secondary Education']

for name, age, major in zip(names, ages, majors):
    print(f'{name} is {age} years old and studies {major}')

NOTES

  • you can zip as many lists as you want
  • The size of the tuple you get out depends on the number of lists you zip
In [ ]:
fruits = ['apple', 'pear', 'blueberry', 'grape', 'strawberry']
plant_types = ['tree', 'tree', 'bush', 'vine']

for fruit, plant_type in zip(fruits, plant_types):
    print(f'The {fruit} grows on a {plant_type}.')

NOTES

  • Zip stops as soon as one of the input lists runs out.
  • Be careful!
In [ ]:
word1 = 'planter'
word2 = 'started'

for letter1, letter2 in zip(word1, word2):
    if letter1 == letter2:
        print(f'{letter1} == {letter2} ✅')
    else:
        print(f'{letter1} != {letter2}')
In [ ]:
 

NOTES

  • You can zip anything you can iterate: lists, strings, etc.

tuple vs list¶

list tuple
Typically stores items of the same type Often stores items of different types
The items are usually independent of each other The items usually go together as a unit of information
Can add or remove items Immutable
Size dynamically determined at runtime Size defined in source code
Typically processed through iteration Typically processed by unpacking

Right Tool for the Job¶

Hold a bunch of numbers that I want to add together (I'll know how many numbers at runtime).

list

Return a first name, family name, and birthdate from a function.

tuple

Stores a pair of items returned from zip

tuple

Keep track of all inputs greater than 7.

list

👨🏿‍🎨 top_team.py¶

You have a list of teams and four lists of total games won for each team for a given season. So, each item in the list represents how many games a given team won:

teams = ['ASU', 'BYU', 'UVU', 'UofU', 'USU', 'BSU']
season1 = [3, 12, 8, 11, 4, 7]
season2 = [2, 11, 3, 11, 2, 6]
season3 = [1, 10, 11, 11, 4, 12]
season4 = [3, 12, 7, 11, 1, 8]

You want to know the name and record of the winningest team, meaning the team that has won the most games, totaled over all seasons.

e.g.

BYU
(12, 11, 10, 12)

Write a program to help you.

top_team.py¶

In [ ]:
import random


def generate_season_wins(teams):
    ''' Generates a list that contains a random amount of wins, one per team '''
    games_won = []
    for team in teams:
        wins = random.randint(1, 10)
        games_won.append(wins)
    return games_won

teams = ['RedApples', 'FuzzyPeaches', 'SweetPears', 'GoneBananas', 'CleverKumquats', 'Oranges']
season1 = generate_season_wins(teams)
season2 = generate_season_wins(teams)
season3 = generate_season_wins(teams)
season4 = generate_season_wins(teams)

print(f'Teams: {teams}')
print(f'Season 1: {season1}')
print(f'Season 2: {season2}')
print(f'Season 3: {season3}')
print(f'Season 4: {season4}')

most_wins = 0
top_team = None
top_record = None

# find the winningest team
# start by zipping the teams and the amount of wins in each season
for name, s1, s2, s3, s4 in zip(teams, season1, season2, season3, season4):
    # each time through this loop we are looking at one team and all their wins in each of the four seasons
    # add up these wins to get the total wins across all 4 seasons
    total_wins = s1 + s2 + s3 + s4
    # check if this is larger than the most wins we have seen so far
    if total_wins > most_wins:
        # if this is the most wins we have seen so far, keep track of this team, their wins, and their record
        most_wins = total_wins
        top_team = name
        top_record = (s1, s2, s3, s4)

print()
print('Top Team:', top_team)
print('Most Wins:', most_wins)
print('Wins Per Season:', top_record)

Key Ideas¶

  • tuple
  • Unpacking
  • Returning multiple values
    • Return a tuple, unpack the return value
  • zip
    • pairwise iteration of two or more sequences
    • stops when the shortest sequence runs out
  • tuple vs list

Appendix¶

🧑🏻‍🎨 Making Reservations¶

You have a list of campsites and their availability. You and two other families want to go camping together for as long as possible. There is a trio of camp sites right next to each other that you would like to reserve, but you need to determine which dates give you the longest time together.

Write a program that determines the dates in the largest window where all three sites are available.

</br>

🏕 🏕 🏕

Input

3 lists of the format:

[
    ('2022/07/04', 'Unavailable'),
    ('2022/07/05', 'Available'),
    ('2022/07/06', 'Available'),
    ('2022/07/07', 'Unavailable'),
    ('2022/07/08', 'Unavailable'),
]

Ouptut

A list of the format:

['2022/07/05', '2022/07/06']
In [ ]:
# solution

# we are going to keep track of every open window. An open window is a list of dates where all three sites
# are available
open_windows = []
# the current window is what we use to accumualte a list of dates where all three sites are available
current_window = []

# loop through the zipped tuples (date, site1availability, site2availability, site3availability)
for date, s1, s2, s3 in zip(dates, site1, site2, site3):
    # if all three sites are available...
    if s1 == 'Available' and s1 == s2 and s1 == s3:
        # ... add this date to the current window
        current_window.append(date)
    else:
        # ... otherwise, add the current window to our list of open windows
        open_windows.append(current_window)
        # and reset the current window to be empty
        current_window = []
# when we exit the loop, we have a current window, so add it to the list of windows
open_windows.append(current_window)

# Find the longest window out of all of the open windows
# Note that open_windows is a list of lists! We need to loop through it and find the longest list
max_window = None
for window in open_windows:
    if max_window is None or len(window) > len(max_window):
        max_window = window

# Print the dates in the maximum open window
print(max_window)