Dictionaries (Advanced)#

Goals of this lecture#

  • Brief dictionary review.

  • Nested dictionaries.

  • Optional dictionary practice problems.

Review: dictionaries#

In Python, a dictionary, or dict, is a mutable collection of items, which stores key/value pairings.

example_dict = {'Name': 'Sean Trott',
               'Occupation': 'Assistant Teaching Professor'}
print(example_dict['Name'])
print(example_dict['Occupation'])
Sean Trott
Assistant Teaching Professor

Nested dictionaries#

A nested dictionary is a dictionary contained inside another dictionary, i.e., as a value.

In principle, there is no limit on how many nested dictionaries can be contained in a dict (besides memory capacity on one’s computer).

  • A nested dictionary is useful when you want to store complex information in each entry.

  • So far, we’ve dealt mostly with very simple key/value entries.

  • But what if we wanted to represent more complicated information?

Example, for each instructor in CSS (or COGS, etc.), store:

  • username.

  • Name.

  • Courses (a list).

  • Department

  • Title.

Check-in (conceptual)#

What would be a useful dict structure to represent information about instructors? For example, say we wanted to represent:

  • username (e.g., sttrott)

  • Name (e.g., Sean Trott)

  • Courses (e.g., ['COGS 14A', ...])

  • Department (e.g., COGS)

  • Title (e.g., Assistant Teaching Professor)

A possible implementation#

One approach is to use nested dictionaries.

  • At the top level, each instructor is represented by their username.

  • Each PID then maps onto a nested dictionary, which contains their Name, Email, and any other info we need.

instructors = {
    'sttrott': {'Name': 'Sean Trott',
                'Courses': ['COGS 14A', 'CSS 1', 'CSS 2'],
               'Title': 'Assistant Teaching Professor',
               'Department': 'COGS'},
    'sellis': {'Name': 'Shannon Ellis',
                'Courses': ['COGS 18', 'COGS 108', 'COGS 137'],
               'Title': 'Associate Teaching Professor',
               'Department': 'COGS'},
    'wstyler': {'Name': 'Will Styler',
                'Courses': ['LING 6', 'LING 101'],
               'Title': 'Director of CSS',
               'Department': 'LING'},
}

Indexing our nested dict#

We can index into this dict as we would normally. Note that now, the value is itself a dict.

instructors['sellis']
{'Name': 'Shannon Ellis',
 'Courses': ['COGS 18', 'COGS 108', 'COGS 137'],
 'Title': 'Associate Teaching Professor',
 'Department': 'COGS'}

Check-in#

How might we index the Title of a particular instructor? I.e., what if we wanted to find out the Title of sttrott?

### Your code here

Nested indices#

Indexing into a nested dictionary follows the same logic––we can chain together index statements to retrieve a particular value.

instructors['sttrott']['Title']
'Assistant Teaching Professor'
instructors['sttrott']['Department']
'COGS'

Check-in#

How would you retrieve the list of usernames (i.e., keys) in this dict?

Solution#

usernames = instructors.keys()
print(usernames)
dict_keys(['sttrott', 'sellis', 'wstyler'])

Practice problems#

These are practice problems that are particularly challenging or advanced. I’ve included them in case:

  • The question occurred to you (i.e., you want to know how to sort by value).

  • You’re keen to get some more hands-on practice with Python.

  • There’s extra time in lecture to review them.

Problem: Sorting a nested dictionary#

How would you sort a nested dictionary, e.g., instructors, by key?

instructors = {
    'sttrott': {'Name': 'Sean Trott',
                'Courses': ['COGS 14A', 'CSS 1', 'CSS 2'],
               'Title': 'Assistant Teaching Professor',
               'Department': 'COGS'},
    'sellis': {'Name': 'Shannon Ellis',
                'Courses': ['COGS 18', 'COGS 108', 'COGS 137'],
               'Title': 'Associate Teaching Professor',
               'Department': 'COGS'},
    'wstyler': {'Name': 'Will Styler',
                'Courses': ['LING 6', 'LING 101'],
               'Title': 'Director of CSS',
               'Department': 'LING'},
}

Solution#

The solution ends up being the same as sorting a simpler dictionary.

instructors_sorted = {i: instructors[i] for i in sorted(instructors)}
instructors_sorted
{'sellis': {'Name': 'Shannon Ellis',
  'Courses': ['COGS 18', 'COGS 108', 'COGS 137'],
  'Title': 'Associate Teaching Professor',
  'Department': 'COGS'},
 'sttrott': {'Name': 'Sean Trott',
  'Courses': ['COGS 14A', 'CSS 1', 'CSS 2'],
  'Title': 'Assistant Teaching Professor',
  'Department': 'COGS'},
 'wstyler': {'Name': 'Will Styler',
  'Courses': ['LING 6', 'LING 101'],
  'Title': 'Director of CSS',
  'Department': 'LING'}}

Problem: Sorting by value#

What if we wanted to sort fruits_dict by value––i.e., such that orange should go before banana?

This ends up being considerably more complicated! We’ll rely on:

  • The ability to use a custom sorting mechanism in sorted.

  • Wrapping a list of tuples in a call to dict.

### How can we make sure "banana" goes last?
fruits_dict
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Input In [10], in <cell line: 2>()
      1 ### How can we make sure "banana" goes last?
----> 2 fruits_dict

NameError: name 'fruits_dict' is not defined

Part 1: sort items by value#

First, we can sort our list of items.

By default, calling sorted will sort by the first element in each tuple.

## By default, sorts by first element
sorted(fruits_dict.items())
[('apple', 2), ('banana', 5), ('orange', 3)]

However, we can use a lambda operator (to be discussed more next week), to tell Python we want to instead sort by the second element.

## Sort instead by second element
sorted(fruits_dict.items(), 
       ### This retrieves the *second* element in a tuple instead
       key = lambda item: item[1])
[('apple', 2), ('orange', 3), ('banana', 5)]

Part 2: sort items by value#

Now, we can wrap that sorted list of items in a call to dict.

fruits_sorted_value = dict(
    sorted(fruits_dict.items(), 
           key = lambda item: item[1]))
fruits_sorted_value
{'apple': 2, 'orange': 3, 'banana': 5}