For loops 2 - iterating dictionaries

Download exercises zip

Browse file online

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

  1. for x in {'a':1,'b':2,'c':3}:
        print(x)
    
  2. for x in {1:'a',2:'b',3:'c'}:
        print(x)
    
  3. diz = {'a':1,'b':2,'c':3}
    for x in diz:
        print(x[diz])
    
  4. diz = {'a':1,'b':2,'c':3}
    for x in diz:
        print(diz[x])
    
  5. diz = {'a':1,'b':2,'c':3}
    for x in diz:
        if x == 'b':
            print(diz[x])
    
  6. for k,v in {1:'a',2:'b',3:'c'}:
        print(k,v)
    
  7. for x in {1:'a',2:'b',3:'c'}.values():
        print(x)
    
  8. for x in {1:'a',2:'b',3:'c'}.keys():
        print(x)
    
  9. for x in {1:'a',2:'b',3:'c'}.items():
        print(x)
    
  10. 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])
Show answer

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
Show solution
[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
Show solution
[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}
Show solution
[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}
Show solution
[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 €
Show solution
[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
Show solution
[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
Show solution
[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:

  • ‘PREPOSITION PLACE’ the smog is excessive if the value is greater than 30

  • ‘PREPOSITION PLACE’ the smog is tolerable otherwise

  • 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
Show solution
[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}
Show solution
[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}
Show solution
[16]:
#jupman-ignore-output
search = {'i','t','r'}
text = "A diurnal lizard of green and brown color."
counts = {}

# write here


{'i': 2, 'r': 5, 't': 0}
{'i': 2, 'r': 5, 't': 0}

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 answer

X 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 !!
Show answerShow solution
[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'}
Show solution
[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']}
Show solution
[19]:

mine = {'brass': 5,
        'iron'  : 8,
        'copper' : 1}
extracted = {}

# write here


Continue

Go on with nested for loops