Week 9: Dictionaries

Reading: Think Python Chapter 11

(You can skip 11.4 - Reverse Lookup)

Notes

Keys and Values

So far, we have seen lists and strings, ordered collections that are indexed based on the position of their content.

Dictionaries, or dicts, are unordered, and consist of pairs of keys and values. They are created with curly braces { and } but indexed with square brackets [ and ].

years = {'DE': 1787, 'MD': 1788, 'VA': 1788}
years['DE']
1787

Note how the keys and values are separated by a colon :.

New elements can be added to a dictionary via indexing and assignment:

years['NC'] = 1788
years
{'DE': 1787, 'MD': 1788, 'VA': 1788, 'NC': 1788}

Dicts are mutable in the same way that lists are.

years['NC'] += 1
years
{'DE': 1787, 'MD': 1788, 'VA': 1788, 'NC': 1789}

Dictionaries are very useful for counting problems. Here’s an example.

This program counts the occurrences of each letter in a string:

You can check if some value is a dictionary key with the in keyword:

years = {'DE': 1787, 'MD': 1788, 'VA': 1788}
'DE' in years
True
'NJ' in years
False

You can extract the keys and values of a dict with the built-in methods <dict>.keys() and <dict>.values():

years.keys()
dict_keys(['DE', 'MD', 'VA'])
years.values()
dict_values([1787, 1788, 1788])

These output special dict_keys and dict_values objects. You can covert these to lists with the list function:

list(years.values())
[1787, 1788, 1788]

Calling len on a dict will give you the number of key-value pairs:

len(years)
3
What can be a key?

Any immutable value, such as ints, floats, and strings, can be a key.

Mutable data types such as lists and other dicts cannot be keys.

Iterating

Looping through a dict with a while loop is cumbersome; using a for loop, it is straightforward. Content iteration over a dict iterates over the keys:

Global Variables

  • You have seen how variables created inside of functions only exist inside of functions
  • We have passed variables in to functions as arguments
  • Functions can also read variables from outside of functions
    • Variables outside of functions are called “global” variables
    • Functions cannot assign to global variables

It is possible to allow a function to assign to a global variable by using the keyword global:

Without Line 2, this program would result in an error.

In practice, you should not reference global variables from functions. Pass arguments in and use return values.

Practice

Practice Problem 9.1

Practice Problem 9.1

Write a function frequency_dict that takes as argument a string and returns a dictionary of character frequencies.

Practice Problem 9.2

Practice Problem 9.2

Write a function frequent_char that takes as argument a string and returns whichever character in the string appears most frequently (assume this will be a unique character).

Practice Problem 9.3

Practice Problem 9.3

Write a function dict_update that takes two arguments: a dictionary and a string.

  • All keys in the dictionary will be strings
  • All values in the dictionary will be ints
  • If the dictionary already contains the string argument, add one to that string’s value
  • If the dictionary does not contain the string argument, add the string to the dictionary as a key, with value 1

Examples:

d = {'JFK': 4, 'DCA': 2}
r = dict_update(d, 'JFK')
print(r)
{'JFK': 5, 'DCA': 2}
d = {'JFK': 4, 'DCA': 2}
r = dict_update(d, 'IAD')
print(r)
{'JFK': 4, 'DCA': 2, 'IAD': 1}

Practice Problem 9.4

Practice Problem 9.4

Write a function small_value that takes as argument a dictionary and returns the key that has the smallest value. All values will be numbers.

  • small_value({'JFK': 5, 'DCA': 2}) returns 'DCA'
  • small_value({'JFK': 4, 'DCA': 2, 'IAD': 1}) returns 'IAD'

Homework

  • Homework problems should always be your individual work. Please review the collaboration policy and ask the course staff if you have questions.

  • Double check your file names and return values. These need to be exact matches for you to get credit.

Homework Problem 9.1

Homework Problem 9.1 (35 pts)

Write a function no_mode that takes as argument a list of ints. Without modifying the original list:

  • Find the int that appears most frequently in the list
  • Create a new list with the same contents
  • Remove all instances of the most-frequently-occurring int
  • Returns the new list.

You can assume that one number will appear more than the others.

  • no_mode([1, 3, 1, 6, 2]) returns [3, 6, 2]
  • no_mode([4, 5, 0, 0]) returns [4, 5]
  • no_mode([1, 1, 2, 2, 2]) returns [1, 1]

Submit as no_mode.py.

Homework Problem 9.2

Homework Problem 9.2 (30 pts)

Write a function common_char that takes as argument a list of strings, counts total occurrences of all characters across all strings, and returns the character that appears most commonly. You can assume there will be a single most common character.

Type hint: the return value should be a character.

  • common_char(['flower', 'rind']) returns r
  • common_char(['bread', 'butter', 'treats']) returns t
  • common_char(['sun', 'moon', 'rain']) returns n

Submit as common_char.py.

Homework Problem 9.3

Homework Problem 9.3 (35 pts)

Write a function unique_words that takes as input a string, which will represent English-language text. Return a list of unique words found in the string. Ignore capitalization (return all lowercase, except the word 'I'). Remove any punctuation: periods, commas, exclamation points, apostrophes, quotation marks, and question marks. Order in the returned list does not matter.

Examples:

a_string = "I know you know."
unique = unique_words(a_string)
print(unique)
['I', 'know', 'you']
a_string = "A good idea, a lot of good."
unique = unique_words(a_string)
print(unique)
['a', 'good', 'idea', 'lot', 'of']
a_string = "To be, or not to be?"
unique = unique_words(a_string)
print(unique)
['to', 'be', 'or', 'not']

Submit as unique_words.py.