Dictionaries, Part 3 (+tuples, + sorting, +state machines)
So far we have created dictionaries and added items to dictionaries, now we need to loop over them.
Two methods: keys()
and values()
keys()
returns a dict_keys
object that contains a list of keys
fruit_prices = {'banana': 0.5, 'apple': 0.75, 'pear': 1.00, 'peach': 1.50, 'apricot': 0.25, 'pineapple': 3.00}
fruits = fruit_prices.keys()
# this is not actually a list
# it is actually a dict_keys object that automatically changes every time the dictionary keys change
print(fruits)
fruit_prices['plum'] = 0.10
print(fruits)
dict_keys(['banana', 'apple', 'pear', 'peach', 'apricot', 'pineapple'])
dict_keys(['banana', 'apple', 'pear', 'peach', 'apricot', 'pineapple', 'plum'])
you can iterate over the dictionary keys
# for you, the prices are double
fruit_prices = {'banana': 0.5, 'apple': 0.75, 'pear': 1.00, 'peach': 1.50, 'apricot': 0.25, 'pineapple': 3.00}
for fruit in fruit_prices.keys():
print(f"The {fruit} costs ${fruit_prices[fruit]*2}")
The banana costs $1.0
The apple costs $1.5
The pear costs $2.0
The peach costs $3.0
The apricot costs $0.5
The pineapple costs $6.0
values()
returns a dict_values
object that contains a list of values
fruit_prices = {'banana': 0.5, 'apple': 0.75, 'pear': 1.00, 'peach': 1.50, 'apricot': 0.25, 'pineapple': 3.00}
prices = fruit_prices.values()
# this is not actually a list
# it is actually a dict_values object that automatically changes every time the dictionary values change
print(prices)
fruit_prices['plum'] = 0.10
print(prices)
dict_values([0.5, 0.75, 1.0, 1.5, 0.25, 3.0])
dict_values([0.5, 0.75, 1.0, 1.5, 0.25, 3.0, 0.1])
you can iterate over the dictionary values
fruit_prices = {'banana': 0.5, 'apple': 0.75, 'pear': 1.00, 'peach': 1.50, 'apricot': 0.25, 'pineapple': 3.00}
for price in fruit_prices.values():
print(price)
0.5
0.75
1.0
1.5
0.25
3.0
Tuples
A tuple is ordered and immutable
- like a list, but you can’t change it
fruits = ("apples", "bananas", "cherry")
print(fruits)
print(f"I like to eat, eat, eat {fruits[0]} and {fruits[1]}!")
('apples', 'bananas', 'cherry')
I like to eat, eat, eat apples and bananas!
You can’t change tuples!
fruits = ("apples", "bananas", "cherry")
# can't change it!
fruits[0] = 'apricots'
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/var/folders/9x/cb134v3d2nb22_rksynbspqm0000gn/T/ipykernel_27566/3571995762.py in <module>
2
3 # can't change it!
----> 4 fruits[0] = 'apricots'
TypeError: 'tuple' object does not support item assignment
Tuples are super helpful when you want to return more than one item from a function
fruit_prices = {'banana': 0.5, 'apple': 0.75, 'pear': 1.00, 'peach': 1.50, 'apricot': 0.25, 'pineapple': 3.00}
def lookup_price(fruit_prices, fruit):
return (fruit, fruit_prices[fruit])
result = lookup_price(fruit_prices, 'peach')
print(result[0], result[1])
peach 1.5
You can unpack tuples!
fruit_prices = {'banana': 0.5, 'apple': 0.75, 'pear': 1.00, 'peach': 1.50, 'apricot': 0.25, 'pineapple': 3.00}
def lookup_price(fruit_prices, fruit):
return (fruit, fruit_prices[fruit])
fruit, price = lookup_price(fruit_prices, 'peach')
print(f"A {fruit} costs ${price}.")
A peach costs $1.5.
Dictionary items
items()
returns a dict_items
object that contains a list of tuples
fruit_prices = {'banana': 0.5, 'apple': 0.75, 'pear': 1.00, 'peach': 1.50, 'apricot': 0.25, 'pineapple': 3.00}
items = fruit_prices.items()
print(items)
# dict_items automatically changes every time the dictionary keys change
fruit_prices['plum'] = 0.10
print(items)
dict_items([('banana', 0.5), ('apple', 0.75), ('pear', 1.0), ('peach', 1.5), ('apricot', 0.25), ('pineapple', 3.0)])
dict_items([('banana', 0.5), ('apple', 0.75), ('pear', 1.0), ('peach', 1.5), ('apricot', 0.25), ('pineapple', 3.0), ('plum', 0.1)])
You can iterate over the dictionary items
fruit_prices = {'banana': 0.5, 'apple': 0.75, 'pear': 1.00, 'peach': 1.50, 'apricot': 0.25, 'pineapple': 3.00}
# for you the prices are half off
for item in fruit_prices.items():
print(f"The {item[0]} costs ${item[1]/2}.")
The banana costs $0.25.
The apple costs $0.375.
The pear costs $0.5.
The peach costs $0.75.
The apricot costs $0.125.
The pineapple costs $1.5.
You can unpack the items as you iterate!
fruit_prices = {'banana': 0.5, 'apple': 0.75, 'pear': 1.00, 'peach': 1.50, 'apricot': 0.25, 'pineapple': 3.00}
# for you the prices are half off
for fruit, price in fruit_prices.items():
print(f"The {fruit} costs ${price/2}.")
The banana costs $0.25.
The apple costs $0.375.
The pear costs $0.5.
The peach costs $0.75.
The apricot costs $0.125.
The pineapple costs $1.5.
You can’t use indexing on dict_keys
, dict_values
, or dict_items
unless you
turn them into a regular list first
fruit_prices = {'banana': 0.5, 'apple': 0.75, 'pear': 1.00, 'peach': 1.50, 'apricot': 0.25, 'pineapple': 3.00}
items = fruit_prices.items()
first_item = list(items)[0]
print(first_item)
('banana', 0.5)
Sorting lists and list-like objects
Use the sorted()
method to sort a list or a list-like object (keys, values,
items)
fruit_prices = {'banana': 0.5, 'apple': 0.75, 'pear': 1.00, 'peach': 1.50, 'apricot': 0.25, 'pineapple': 3.00}
for fruit, price in sorted(fruit_prices.items()):
print(f"The {fruit} costs ${price/2}.")
names = ['John', 'Ezekiel', 'Abby', 'Ellen']
print(sorted(names))
The apple costs $0.375.
The apricot costs $0.125.
The banana costs $0.25.
The peach costs $0.75.
The pear costs $0.5.
The pineapple costs $1.5.
['Abby', 'Ellen', 'Ezekiel', 'John']
State Machine Pattern
State Machine Pattern
- initialize a state variable
- loop over the elements
- check and potentially update the state
- use the state variable to return the final result
Find the earliest letter in a word.
def find_earliest_letter(word):
# initialize state variable
earliest = None
for letter in word:
if earliest is None or letter < earliest:
earliest = letter
print(f"earliest letter is now {earliest}")
return earliest
result = find_earliest_letter('zoomba')
print(result)
result = find_earliest_letter('zombie')
print(result)
earliest letter is now z
earliest letter is now o
earliest letter is now m
earliest letter is now b
earliest letter is now a
a
earliest letter is now z
earliest letter is now o
earliest letter is now m
earliest letter is now b
b
Another state machine example: decode 'xxyy9H%vvv%2i%t6!'
- get the first character after every digit
def decode(message):
# accumulator variable
result = ''
# state variable
get_next = False
for character in message:
if get_next:
result += character
get_next = False
elif character.isdigit():
get_next = True
return result
message = decode('xxyy9H%vvv%2i%t6!')
print(message)
message = decode('abc!#$2C3S111100')
print(message)
Hi!
CS110
And another state machine example
- count the number of duplicates in a list of numbers
def count_duplicates(numbers):
# initialize count
count = 0
# keep track of previous number
previous = None
for number in numbers:
if previous == number:
# found a duplicate
count += 1
# reset previous
previous = number
return count
result = count_duplicates([1, 1, 2, 3, 3, 4, 4, 4, 4, 5])
print(result)
5
Find the cheapest price
fruit_prices = {'banana': 0.5, 'apple': 0.75, 'pear': 1.00, 'peach': 1.50, 'apricot': 0.25, 'pineapple': 3.00}
def find_min_price(fruit_prices):
values = fruit_prices.values()
# assume the first price is the cheapest until we are proven wrong
# need to convert the values to a list so we can get the first one
min_price = list(values)[0]
for price in values:
if price < min_price:
# update the new minimum price
min_price = price
return min_price
price = find_min_price(fruit_prices)
print(price)
0.25
What if we want to find the name of the item that is the cheapest, in addition to the price?
- We can use tuples!
fruit_prices = {'banana': 0.5, 'apple': 0.75, 'pear': 1.00, 'peach': 1.50, 'apricot': 0.25, 'pineapple': 3.00}
def find_min_price(fruit_prices):
items = fruit_prices.items()
# convert the items to a list and get the first one
# we can assume the first item is the cheapest until we are proven wrong
cheapest = list(items)[0]
for fruit, price in items:
# unpack the tuple
cheapest_fruit, cheapest_price = cheapest
if price < cheapest_price:
# update the cheapest item
cheapest = (fruit, price)
# return a tuple
return cheapest
# unpack the tuple
fruit, price = find_min_price(fruit_prices)
print(f"The cheapest item is the {fruit} that costs ${price}.")
The cheapest item is the apricot that costs $0.25.