For loops 2 - iterating dictionaries¶
Download exercises zip¶
Given a dictionary, we can examinate the sequence of its keys, values or both with a for
cycle.
Iterating keys¶
To iterate only the keys it is sufficient to use the in
operator:
WARNING: keys iteration order is not predictable !
[2]:
pastries = {
'cream puff':5,
'brioche':8,
'donut':2
}
[3]:
for key in pastries:
print('Found key :', key)
print(' with value:', pastries[key])
Found key : cream puff
with value: 5
Found key : brioche
with value: 8
Found key : donut
with value: 2
At each iteration, the declared variable key
is assigned to a key taken from the dictionary, in an order we cannot predict.
Iterating key-value pairs¶
We can also directly obtain both the key and the associated value with this notation:
[4]:
for key, value in pastries.items():
print('Found key :', key)
print(' with value:', pastries[key])
Found key : cream puff
with value: 5
Found key : brioche
with value: 8
Found key : donut
with value: 2
.items()
return a list of key/value couples, and during each iteration a couple is assigned to the variable key
and value
.
Iterating values¶
We can iterate the values calling the method values()
WARNING: values iteration order is also not predictable !
[5]:
for value in pastries.values():
print('Found value', value)
Found value 5
Found value 8
Found value 2
Questions - iteration¶
Look at the following code fragments , and for each try guessing the result it produces (or if it gives an error):
WARNING: Remember the order is IMPOSSIBLE to foresee, so the important bit is to guess all the printed stuff
for x in {'a':1,'b':2,'c':3}: print(x)
for x in {1:'a',2:'b',3:'c'}: print(x)
diz = {'a':1,'b':2,'c':3} for x in diz: print(x[diz])
diz = {'a':1,'b':2,'c':3} for x in diz: print(diz[x])
diz = {'a':1,'b':2,'c':3} for x in diz: if x == 'b': print(diz[x])
for k,v in {1:'a',2:'b',3:'c'}: print(k,v)
for x in {1:'a',2:'b',3:'c'}.values(): print(x)
for x in {1:'a',2:'b',3:'c'}.keys(): print(x)
for x in {1:'a',2:'b',3:'c'}.items(): print(x)
for x,y in {1:'a',2:'b',3:'c'}.items(): print(x,y)
Questions - Are they equivalent?¶
Look at the following code fragments: each contains two parts, A and B. For each fragment, try guessing whether part A will print exactly the same result printed by code in part B
FIRST think about the answer
THEN try executing
Are they equivalent ? postin¶
diz = {
'p':'t',
'o':'i',
's':'n',
}
print('A:')
for x in diz.keys():
print(x)
print('\nB:')
for y in diz:
print(y)
Are they equivalent ? cortel¶
diz = {
'c':'t',
'o':'e',
'r':'l',
}
print('A:')
for p,q in diz.items():
print(q)
print('\nB:')
for x in diz.values():
print(x)
Are they equivalent ? - gel¶
diz = {
'g':'l',
'e':'e',
'l':'g',
}
print('A:')
for x in diz.values():
print(x)
print('\nB:')
for z in diz.items():
print(z[0])
Are they equivalent ? - giri¶
diz = {
'p':'g',
'e':'i',
'r':'r',
'i':'i',
}
print('A:')
for p,q in diz.items():
if p == q:
print(p)
print('\nB:')
for x in diz:
if x == diz[x]:
print(x)
Are they equivalent? - Found¶
First think if they are equivalent, then check with all the proposed values of k
.
Be very careful about this exercise !
Getting this means having really understood dictionaries ;-)
k = 'w'
#k = 'h'
#k = 'y'
#k = 'z'
dct = {
'w':'s',
'h':'o',
'y':'?',
}
print('A:')
for x in dct:
if x == k:
print('Found', dct[x])
print('\nB:')
if k in dct:
print('Found', dct[k])
Iteration exercises¶
Exercise - color of hearts¶
✪ Write some code which given a dictionary suits
, for each suits prints its color.
Example - given:
suits = {
'hearts':'red',
'spades':'black',
'diamonds':'red',
'clubs':'black'
}
Prints:
WARNING: do not care about the order in which values are printed!
On your computer you might see different results, the important bit is that all rows get printed.
The color of spades is black
The color of diamonds is red
The color of hearts is red
The color of clubs is black
[6]:
suits = {
'hearts':'red',
'spades':'black',
'diamonds':'red',
'clubs':'black'
}
# write here
Exercise - jewels¶
✪ In the dictionary jewels
some keys are equal to the respective values. Write some code which find such keys and prints them all.
Example - given:
jewels = {
'rubies': 'jade',
'opals':'topazes',
'gems':'gems',
'diamonds': 'gems',
'rubies':'rubies'
}
prints:
couple of equal elements: gems and gems
couple of equal elements: rubies and rubies
[7]:
jewels = {
'rubies': 'jade',
'opals':'topazes',
'gems':'gems',
'diamonds': 'gems',
'rubies':'rubies'
}
# write here
Exercise - powers¶
✪ Given a number n
, write some code which creates a NEW dictionary d
containing as keys the numbers from 1 a n
INCLUDED, by associating keys to their squares.
Example - given:
n = 5
after your code, it must result:
>>> print(d)
{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
[8]:
n = 5
# write here
Exercise - flowers¶
✪ Given a list flowers
, write some code which creates a NEW dictionary is_cap
which associates to each flower True
if the flower name is written all uppercase, and False
otherwise
HINT: to verify whether a string is all uppercase, use
.isupper()
method
flowers = ['sunflower','GILLYFLOWER', 'tulip', 'PASSION FLOWER', 'ROSE', 'violet']
prints (they are in alphabetical order because we print with pprint
):
>>> from pprint import pprint
>>> pprint(is_cap)
{'GILLYFLOWER': True,
'PASSION FLOWER': True,
'ROSE': True,
'sunflower': False,
'tulip': False,
'violet': False}
[9]:
flowers = ['sunflower','GILLYFLOWER', 'tulip', 'PASSION FLOWER', 'ROSE', 'violet']
# write here
Exercise - art¶
✪ An artist painted a series of works with different techiques. In the dictionary prices
he writes the price of each technique. The artist intend to promote a series of exhibitions, and in each of them he will present a particular technique. Supposing for each technique he produced q
paintings, show how much he will learn in each exhibition (suppose he sells everything).
Example - given:
q = 20
exhibitions = ['watercolor', 'oil', 'mural', 'tempera', 'charcoal','ink']
prices = {'watercolor': 3000,
'oil' : 6000,
'mural' : 2000,
'tempera' : 4000,
'charcoal' : 7000,
'ink' : 1000
}
Prints - this time order matters!!
Expected Income:
exhibition watercolor : 60000 €
exhibition oil : 120000 €
exhibition mural : 40000 €
exhibition tempera : 80000 €
exhibition charcoal : 140000 €
exhibition ink : 20000 €
[10]:
q = 20
exhibitions = ['watercolor', 'oil', 'mural', 'tempera', 'charcoal','ink']
prices = {'watercolor': 3000,
'oil' : 6000,
'mural' : 2000,
'tempera' : 4000,
'charcoal' : 7000,
'ink' : 1000
}
# write here
Exercise - stationery stores¶
✪ An owner of two stationery shops, in order to reorganize the stores wants to know the materials which are in common among the shops. Given two dictionaries store1
and store2
which associates objects to their quantity, write some code which finds all the keys in common and for each prints the sum of the found quantities.
Example - given:
store1 = {'pens':10,
'folders':20,
'papers':30,
'scissors':40}
store2 = {'pens':80,
'folders':90,
'goniometer':130,
'scissors':110,
'rulers':120,
}
prints (order is not important):
materials in common:
pens : 90
folders : 110
scissors : 150
[11]:
store1 = {'pens':10,
'folders':20,
'papers':30,
'scissors':40}
store2 = {'pens':80,
'folders':90,
'goniometer':130,
'scissors':110,
'rulers':120,
}
# write here
Exercise - legumes¶
✪ A store has numbered shelves, each containing a number of legumes expressed in kilograms. We represent store
as a list. There is also a registry
available as a dictionary which associates to legume names the shelves number in which they are contained.
Write some code which given a list of legume names, shows the sum of kilograms in the store for those legumes.
Example - given:
legumes = ['lentils', 'soy']
# 0 1 2 3 4 5
store = [50,90,70,10,20,50]
registry = {'peas':3,
'soy':1,
'chickpeas':5,
'lentils':4,
'broad beans':2,
'beans':0,
}
after your code, it must print (order does not matter):
Searching for lentils and soy ...
Found 20 kg of lentils
Found 90 kg of soy
Total: 110 kg
[12]:
legumes = ['lentils', 'soy'] # 110
#legumes = ['beans', 'broad beans', 'chickpeas'] # 170
# 0 1 2 3 4 5
store = [50,90,70,10,20,50]
registry = {'peas':3,
'soy':1,
'chickpeas':5,
'lentils':4,
'broad beans':2,
'beans':0,
}
# write here
Exercise - smog¶
✪ Write some code which given two dictionaries smog
and prepositions
which associate places to respectively values of smog and prepositions, prints all the places telling the smog is excessive if the value is greater than 30, otherwise is tolerable.
NOTE: when printing the first preposition character must be capital: to transform the string you can use the method
.capitalize()
Example - given:
smog = {'streets' : 40,
'cities' : 20,
'intersections' : 90,
'trains' : 15,
'lakes' : 5
}
propositions = {
'streets' : 'on',
'cities' : 'in',
'lakes' : 'at',
'trains' : 'on',
'intersections' : 'at',
}
prints (order does not matter):
On streets the smog level is excessive
In cities the smog level is tolerable
At intersections the smog level is excessive
On trains the smog level is tolerable
At lakes the smog level is tolerable
[13]:
smog = {'streets' : 40,
'cities' : 20,
'intersections' : 90,
'trains' : 15,
'lakes' : 5
}
prepositions = {
'streets' : 'on',
'cities' : 'in',
'lakes' : 'at',
'trains' : 'on',
'intersections' : 'at',
}
# write here
Exercise - sports¶
✪✪ Write some code which given a dictionary sports
in which people are associated to the favourite sport, create a NEW dictionari counts
in which associates each sport to the number of people that prefer it.
Example - given:
sports = {
'Gianni':'soccer',
'Paolo':'tennis',
'Sara':'volleyball',
'Elena':'tennis',
'Roberto':'soccer',
'Carla':'soccer',
}
After your code, it must result:
>>> print(counts)
{'tennis': 2, 'soccer': 3, 'volleyball': 1}
[14]:
sports = {
'Gianni':'soccer',
'Paolo':'tennis',
'Sara':'volleyball',
'Elena':'tennis',
'Roberto':'soccer',
'Carla':'soccer',
}
# write here
{'soccer': 3, 'tennis': 2, 'volleyball': 1}
Exercise - green lizard¶
✪✪ Write some code which given a set search
of characters to find, counts for each how many are present in the string text
and places the number in the dictionary counts
.
Example - given:
[15]:
search = {'i','t','r'}
text = "A diurnal lizard of green and brown color A pattern may also be present in the form of dark slate grey streaks or spots. When found with a brown coloration, sometimes with lighter stripe down the back."
counts = {}
After your code it must result:
>>> print(counts)
{'r': 5, 'i': 2, 't': 0}
[16]:
#jupman-ignore-output
search = {'i','t','r'}
text = "A diurnal lizard of green and brown color."
counts = {}
# write here
{'i': 2, 't': 0, 'r': 5}
{'i': 2, 't': 0, 'r': 5}
Modifying a dictionary during iteration¶
Suppose you have a dictionary of provinces:
provinces = {
'tn': 'Trento',
'mi':'Milano',
'na':'Napoli',
}
and you want to MODIFY it so that after your code the acronyms are added as capitalized:
>>> print(provinces)
{'tn': 'Trento',
'mi':'Milano',
'na':'Napoli',
'TN': 'Trento',
'MI':'Milano',
'NA':'Napoli',
}
You might think to write something like this:
for key in provinces:
provinces[key.upper()] = provinces[key] # WARNING !
QUESTION: Do you see any problem?
Show answerX COMMANDMENT: You shall never ever add nor remove elements from a dictionary you are iterating with a for
!
In this case, if we try executing the code, we will get an explicit error:
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
<ipython-input-26-9b20900057e8> in <module>()
----> 1 for key in provinces:
2 provinces[key.upper()] = provinces[key] # WARNING !
RuntimeError: dictionary changed size during iteration
but in other cases (like for example lists) modifying stuff may produce totally unpredictable behaviours (do you know the expression pulling the rug out from under your feet ? )
What about removing? We’ve seen adding is dangerous, but so is removing.
Suppose we want to remove any couple having as value 'Trento'
provinces = {
'tn': 'Trento',
'mi':'Milano',
'na':'Napoli',
}
to obtain:
>>> print(provinces)
{'mi':'Milano',
'na':'Napoli'}
If we try executing something like this Python notices and raises an exception:
provinces = {
'tn': 'Trento',
'mi':'Milano',
'na':'Napoli',
}
for key in provinces:
if provinces[key] == 'Trento':
del provinces[key] # VERY BAD IDEA
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
<ipython-input-23-5df0fd659120> in <module>()
5 'na':'Napoli'
6 }
----> 7 for key in provinces:
8 if provinces[key] == 'Trento':
9 del provinces[key] # VERY BAD IDEA
RuntimeError: dictionary changed size during iteration
If you really need to remove elements from the sequence in which you are iterating, use a while cycle or first copy the original sequence.
Exercise - zazb¶
✪✪ Write some code which given a dictionary chars
with characters as keys, MODIFY the dictionary so to add keys like the existing ones prefixed with character 'z'
- new keys should be associated with the constant integer 10
Example - given:
chars = {
'a':3,
'b':8,
'c':4
}
after your code, chars
should result MODIFIED like this:
>>> chars
{ 'a':3,
'b':8,
'c':4,
'za':10,
'zb':10,
'zc':10
}
QUESTION: Is it desirable to write a solution like the following one? Read carefully!
chars = {
'a':3,
'b':8,
'c':4
}
for key in chars:
chars['z'+key] = 10 # WARNING !! TROUBLE AHEAD !!
[17]:
chars = {
'a':3,
'b':8,
'c':4
}
# write here
Exercise - DIY¶
✪✪ A depot for do-it-yourself hobbists has a catalog
which associates object types to the shelves where to put them. Each day, a list of entries
is populated with the newly arrived object types. Such types are placed in the depot
, a dictionary which associates to each shelf the object type pointed by the catalof. Write some code which given the list entries
and catalog
, populates the dictionary depot
Example - given:
entries = ['chairs', 'lamps', 'cables']
catalog = {'stoves' : 'A',
'chairs' : 'B',
'carafes' : 'D',
'lamps' : 'C',
'cables' : 'F',
'gardening' : 'E'}
depot = {}
after your code, it must result:
>>> print(depot)
{'B': 'chairs', 'C': 'lamps', 'F': 'cables'}
[18]:
entries = ['chairs', 'lamps', 'cables'] # depot becomes: {'B': 'chairs', 'C': 'lamps', 'F': 'cables'}
#entries = ['carafes', 'gardening'] # depot becomes: {'D': 'carafes', 'E': 'gardening'}
#entries = ['stoves'] # depot becomes: {'A': 'stoves'}
catalog = {'stoves' : 'A',
'chairs' : 'B',
'carafes' : 'D',
'lamps' : 'C',
'cables' : 'F',
'gardening' : 'E'}
depot = {}
# write here
Exercise - mine¶
✪✪ Given a dictionary mine
which associates keys to numbers, MODIFY the dictionary extracted
associating the same keys of mine
to lists with keys repeated the given number of times
Example - given:
mine = {'brass': 5,
'iron' : 8,
'copper' : 1}
extracted = {}
after your code it must result:
>>> print(extracted)
{'brass': ['brass', 'brass', 'brass', 'brass', 'brass'],
'iron': ['iron', 'iron', 'iron', 'iron', 'iron', 'iron', 'iron', 'iron'],
'copper': ['copper']}
[19]:
mine = {'brass': 5,
'iron' : 8,
'copper' : 1}
extracted = {}
# write here
Continue¶
Go on with nested for loops