Dictionaries 3 - Methods

Download exercise zip

Browse online files

In this notebook we will se the main ethods to extract data and manipulate dictionaries.

Methods:

Method

Return

Description

`dict.keys() <#keys-method> `__

dict_keys

Return a view of keys which are present in the dictionary

dict.values()

dict_values

Return a view of values which are present in the dictionary

dict.items()

dict_items

Return a view of (key/value) couples present in the dictionary

dict1.update(dict2)

None

MODIFY the dictionary dict1 with the key / value couples found in dict2

What to do

  1. Unzip exercises zip in a folder, you should obtain something like this:

sets
    dictionaries1.ipynb
    dictionaries1-sol.ipynb
    dictionaries2.ipynb
    dictionaries2-sol.ipynb
    dictionaries3.ipynb
    dictionaries3-sol.ipynb
    dictionaries4.ipynb
    dictionaries4-sol.ipynb
    dictionaries5-chal.ipynb
    jupman.py

WARNING: to correctly visualize the notebook, it MUST be in an unzipped folder !

  1. open Jupyter Notebook from that folder. Two things should open, first a console and then a browser. The browser should show a file list: navigate the list and open the notebook dictionaries3.ipynb

  2. Go on reading the exercises file, sometimes you will find paragraphs marked Exercises which will ask to write Python commands in the following cells.

Shortcut keys:

  • to execute Python code inside a Jupyter cell, press Control + Enter

  • to execute Python code inside a Jupyter cell AND select next cell, press Shift + Enter

  • to execute Python code inside a Jupyter cell AND a create a new cell aftwerwards, press Alt + Enter

  • If the notebooks look stuck, try to select Kernel -> Restart

keys method

By calling the method .keys() we can obtain the dictionary keys:

[2]:
vegetables = {'carrots'  : 5,
              'tomatoes' : 8,
              'cabbage'  : 3}
[3]:
vegetables.keys()
[3]:
dict_keys(['carrots', 'tomatoes', 'cabbage'])

WARNING: THE RETURNED SEQUENCE IS OF TYPE dict_keys

dict_keys might look like a list but it is well different!

In particular, the returned sequence dict_keys is a view on the original dictionary. In computer science, when we talk about views we typically intend collections which contain a part of the objects contained in another collection, and if the original collection gets modified, so is the view at the same time.

Let’s see what this means. First let’s assign the sequence of keys to a variable:

[4]:
ks = vegetables.keys()

Then we modify the original dictionary, adding an association:

[5]:
vegetables['potatoes'] = 8

If we now print ks, we should see the change:

[6]:
ks
[6]:
dict_keys(['carrots', 'tomatoes', 'cabbage', 'potatoes'])

Sequence returned by .keys() can change over time!

When reusing the sequence from .keys(), ask yourself if the dictionary could have changed in the meanwhile

If we want a stable version as a sort of static ‘picture’ of dictionary keys at a given moment in time, we must explicitly convert them to another sequence, like for example a list:

[7]:
as_list = list(vegetables.keys())
[8]:
as_list
[8]:
['carrots', 'tomatoes', 'cabbage', 'potatoes']
[9]:
vegetables['cocumber'] = 9
[10]:
as_list     # no cocumbers
[10]:
['carrots', 'tomatoes', 'cabbage', 'potatoes']

Let’s see again the example in Python Tutor:

[11]:
# WARNING: FOR PYTHON TUTOR TO WORK, REMEMBER TO EXECUTE THIS CELL with Shift+Enter
#          (it's sufficient to execute it only once)

import jupman
[12]:
vegetables = {'carrots'  : 5,
              'tomatoes' : 8,
              'cabbage'  : 3}
keys = vegetables.keys()
vegetables['potatoes'] = 8
as_list = list(vegetables.keys())
vegetables['cocumbers'] = 9
#print(as_list)

jupman.pytut()
[12]:
Python Tutor visualization

WARNING: WE CAN’T USE INDEXES WITH dict_keys

If we try, we will obtain an error:

>>> vegetables = {'carrots'  : 5,
                  'tomatoes' : 8,
                  'cabbage'  : 3}
>>> ks = vegetables.keys()
>>> ks[0]

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-90-c888bf602918> in <module>()
----> 1 keys[0]

TypeError: 'dict_keys' object does not support indexing

WARNING: WE CANNOT DIRECTLY MODIFY dict_keys

There aren’t operations nor methods which allow us to change the elements of dict_keys, you can only act on the original dictionary.

QUESTION: Look at the following code fragments, and for each try guessing if it can work (or if it gives an error):

  1. diz = {'a':4,
           'b':5}
    
    ks = diz.keys()
    ks.append('c')
    
  2. diz = {'a':4,
           'b':5}
    
    ks = diz.keys()
    ks.add('c')
    
  3. diz = {'a':4,
           'b':5}
    
    ks = diz.keys()
    ks['c'] = 3
    
Show answer

QUESTION: Look at the following code fragments, and for each try guessing which result it produces (or if it gives an error):

  1. diz = {'a':1,'b':2}
    s = set(diz.keys())
    s.add(('c',3))
    print(diz)
    print(s)
    
  2. diz = {'a':3,'b':4}
    k = diz.keys()
    diz['c'] = 5
    print(len(k))
    
  3. diz = {'a':'x',
           'b':'y'}
    print('a' in diz.keys())
    
  4. diz1 = {'a':1,'b':2}
    chiavi = diz1.keys()
    diz2 = dict(diz1)
    diz2['c'] = 3
    print('diz1=',diz1)
    print('diz2=',diz2)
    print('chiavi=',chiavi)
    
  5. diz1 = {'a':'b','c':'d'}
    diz2 = {'a':'b','b':'c'}
    print( set(diz1.keys()) - set(diz2.keys())  )
    
  6. diz1 = {'a':'b','c':'d'}
    diz2 = {'e':'a','f':'c'}
    ks = diz1.keys()
    del diz1[diz2['e']]
    del diz1[diz2['f']]
    print(len(ks))
    

Exercise - messy keys

✪ PRINT a LIST with all the keys in the dictionary

  • NOTE 1: it is NOT necessary for the list to be sorted

  • NOTE 2: to convert any sequence to a list, use the predefined function list

Show solution
[13]:

d = {'c':6, 'b':2,'a':5} # write here

Exercise - sorted keys

✪ PRINT a LIST with all the dictionary keys

  • NOTE 1: Now it IS necessary for the list to be sorted

  • NOTE 2: to convert any sequence to a list, use the predefined function list

Show solution
[14]:

d = {'c':6, 'b':2,'a':5} # write here

Exercise - keyring

Given the dictionaries d1 and d2, write some code which puts into a list ks all the keys in the two dictionaries, without duplicates and alphabetically sorted, and finally prints the list.

  • your code must work with any d1 and d2

Example - given:

d1 = {
    'a':5,
    'b':9,
    'e':2,
}
d2 = {'a':9,
      'c':2,
      'e':2,
      'f':6}

after your code, it must result:

>>> print(keys)
['a', 'b', 'c', 'e', 'f']
Show solution
[15]:

d1 = { 'a':5, 'b':9, 'e':2, } d2 = {'a':9, 'c':2, 'e':2, 'f':6} # write here

values method

Given a dictionary, we can obtain all the values by calling the method .values()

Imagine we have a dictionary vehicles which assigns an owner to each car plate:

[16]:
vehicles = {
    'AA111AA' : 'Mario',
    'BB222BB' : 'Lidia',
    'CC333CC' : 'Mario',
    'DD444DD' : 'Gino',
    'EE555EE' : 'Gino'
}

owners = vehicles.values()

WARNING: THE RETURNED SEQUENCE IS OF TYPE dict_values

dict_values may seem a list but it’s not!

We’ve seen dict_keys is a view on the original dictionary, and so is dict_values, thus by adding an association to vehicles

[17]:
vehicles['FF666FF'] = 'Paola'

… the view owners will automatically result changed:

[18]:
owners
[18]:
dict_values(['Mario', 'Lidia', 'Mario', 'Gino', 'Gino', 'Paola'])

We also note that being values of a dictionary, duplicates are allowed.

WARNING: WE CANNOT USE INDEXES WITH dict_values

If we try, we will get an error:

>>> owners[0]

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-90-c888bf602918> in <module>()
----> 1 owners[0]

TypeError: 'dict_values' object does not support indexing

WARNING: WE CANNOT DIRECTLY MODIFY dict_values

There aren’t operations nor methods that allow us to change the elements of dict_values, we can only act on the original dictionary.

QUESTION: Look at the following code fragments, and for each try guessing the result it produces (or if it gives an error):

  1. diz = {'a':4,
           'b':5}
    
    vals = diz.values()
    vals.append(4)
    
  2. d = {0:'a',
         1:'b',
         2:'b'}
    vals = d.values()
    d[2]='c'
    print(vals)
    
  3. diz = {'a':4,
           'b':5}
    
    vals = diz.values()
    vals.add(5)
    
  4. diz = {0:1,
           1:2,
           2:3}
    
    diz[list(diz.values())[0]-1]
    
  5. diz = {'a':4,
           'b':5}
    
    vals = diz.values()
    vals['c'] = 6
    
  6. diz = {'a':4,
           'b':5}
    
    vals = diz.values()
    vals[6] = 'c'
    

Exercise - one by one

Given a dictionary my_dict, write some code which prints True if each key is associated to a value different from the values of all other keys. Otherwise prints False.

Example 1 - given:

my_dict = {'a' : 3,
           'c' : 6,
           'g' : 8}

After your code, it must print True (because 3,6 and 8 are all different)

True

Example 2 - given:

my_dict = {'x' : 5,
           'y' : 7,
           'z' : 5}

it must print:

False
Show solution
[19]:

my_dict = {'a' : 3, 'c' : 6, 'g' : 8} """ my_dict= {'x' : 5, 'y' : 7, 'z' : 5} """ # write here

Exercise - bag

Given a dictionary my_dict of character associations, write some code which puts into the variable bag the sorted list of all the keys and values.

Example - given:

my_dict = {
    'a':'b',
    'b':'f',
    'c':'b',
    'd':'e'
}

After your code, it must print:

>>> print(bag)
['a', 'b', 'c', 'd', 'e', 'f']
Show solution
[20]:

my_dict = { 'a':'b', 'b':'f', 'c':'b', 'd':'e' } # write here

Exercise - common values

Given two dictionaries d1 and d2, write some code which PRINTS True if they have at least a value in common (without considering the keys)

Example 1 - given:

d1 = {
    'a':4,
    'k':2,
    'm':5
}

d2 = {
    'b':2,
    'e':4,
    'g':9,
    'h':1
}

after your code, it must print True (because they have the values 2 and 4 in common):

Common values? True

Example 2 - given:

d1 = {
    'd':1,
    'e':2,
    'f':6
}

d2 = {
    'a':3,
    'b':5,
    'c':9,
    'd':7
}

after your code, it must print:

Common values? False
Show solution
[21]:

d1 = { 'a':4, 'k':2, 'm':5 } d2 = { 'b':2, 'e':4, 'g':9, 'h':1 } """ d1 = { 'd':1, 'e':2, 'f':6 } d2 = { 'a':3, 'b':5, 'c':9, 'd':7 } """ # write here

Exercise - small big

Given a dictionary d which has integers as keys and values, print True if the smaller key is equal to the greatest value.

Example 1 - given:

d = {
    14:1,
    11:7,
     7:3,
    70:5
}

after your code, it must print True (because the smallest key is 7 which is equal to the greates value 7):

True

Example 2 - given:

d = {
    12:1,
    11:9,
     7:3,
     2:5,
     9:1
}

after your code, it must print False (because the smallest key 2 is different from the greatest value9):

False
Show solution
[22]:

d = { 14:1, 11:7, 7:3, 70:5 } """ d = { 12:1, 11:9, 7:3, 2:5, 9:1 } """ # write here

items method

We can extract all the key/value associations as a list of couples of type tuple with the method .items(). Let’s see an example which associates attractions to the city they are in:

[23]:
holiday = {'Piazza S.Marco'  :'Venezia',
           'Fontana di Trevi':'Roma',
           'Uffizi'          :'Firenze',
           'Colosseo'        :'Roma',
}
[24]:
holiday.items()
[24]:
dict_items([('Piazza S.Marco', 'Venezia'), ('Fontana di Trevi', 'Roma'), ('Uffizi', 'Firenze'), ('Colosseo', 'Roma')])

In this case we see that an object of type dict_items is returned. As in previous cases, it is a view which we can’t directly modify. If the original dictionary gets changed, the mutation will be reflected in the view:

[25]:
attractions = holiday.items()
[26]:
holiday['Palazzo Ducale'] = 'Venezia'
[27]:
attractions
[27]:
dict_items([('Piazza S.Marco', 'Venezia'), ('Fontana di Trevi', 'Roma'), ('Uffizi', 'Firenze'), ('Colosseo', 'Roma'), ('Palazzo Ducale', 'Venezia')])

QUESTION: Look at the following code fragments, and for each try guessing which result it produces (or if it gives an error):

  1. {'a':7, 'b':9}.items()[0] = ('c',8)
    
  2. dict({'a':7,'b':5}.items())['a']
    
  3. len(set({'a':'b', 'a':'B'}.items()))
    
  4. {'a':2}.items().find(('a',2))
    
  5. {'a':2}.items().index(('a',2))
    
  6. list({'a':2}.items()).index(('a',2))
    
  7. diz1 = {'a':7,
            'b':5}
    diz2 = dict(diz1.items())
    diz1['a'] = 6
    print(diz1 == diz2)
    
  8. ('a','b') in {'a':('a','b'), 'b':('a','b')}.items()
    
  9. ('a','b') in list({'a':('a','b'), 'b':('a','b')}.items())[0]
    

Exercise - union without update

Given the dictionaries d1 and d2, write some code which creates a NEW dictionary d3 containing all the key/value couples from d1 and d2.

  • we suppose all the key/value couples are distinct

  • DO NOT use cycles

  • DO NOT use .update()

  • your code must work for any d1 and d2

Example - given:

d1 = {'a':4,
      'b':7}
d2 = {'c':5,
      'd':8,
      'e':2}

after your code, it must result (order is not important):

>>> print(d3)
{'a': 4, 'e': 2, 'd': 8, 'c': 5, 'b': 7}
Show solution
[28]:

d1 = {'a':4, 'b':7} d2 = {'c':5, 'd':8, 'e':2} # write here

update method

Having a dictionary to start with, it is possibly to MODIFY it by joining another with the method .update():

[29]:
d1 = {'goats'    :6,
      'cabbage'  :9,
      'shepherds':1}


d2 = {'goats'  :12,
      'cabbage':15,
      'benches':3,
      'hay'    :7}
[30]:
d1.update(d2)
[31]:
d1
[31]:
{'goats': 12, 'cabbage': 15, 'shepherds': 1, 'benches': 3, 'hay': 7}

Note how the common keys among the two dictionaries like 'goats' and 'cabbage' have values from the second.

If we will, it’s also possible to pass a sequence of couples like this:

[32]:
d1.update([('hay',3),('benches',18), ('barns',4)])
[33]:
d1
[33]:
{'goats': 12,
 'cabbage': 15,
 'shepherds': 1,
 'benches': 18,
 'hay': 3,
 'barns': 4}

Exercise - axby

Given a dictionary dcc which associates characters to characters and a string s formatted with couples of characters like ax separated by a semi-colon ;, substitute all the values in dcc with the corresponding values denoted in the string.

  • your code must work for any dictionary my_dict and lists

Example - given:

dcc = {
    'a':'x',
    'b':'y',
    'c':'z',
    'd':'w'
}
s = 'bx;cw;ex'

after your code, it must result:

>>> dcc
{'a': 'x', 'b': 'x', 'c': 'w', 'd': 'w', 'e': 'x'}
Show solution
[34]:

dcc = { 'a':'x', 'b':'y', 'c':'z', 'd':'w' } s = 'bx;cw;ex' # write here

Continue

Go on with Dictionaries 4