Dictionaries

A dictionary is datatype that contains a series of key-value pairs. It is similar to a list except for that the indices of the values can be strings, tuples, etc. not just integers. It is also different in that it is unordered. You cannot expect to get the keys in the same order out as you put them in.

To create a dictionary:

my_dict = { key1: value1, key2: value2 }

Creating an empty dictionary

my_dict = {} 
my_dict = dict()

In [21]:
fruit_season = {
    'raspberry': 'May',
    'apple'    : 'September',
    'peach'    : 'July',
    'grape'    : 'August'
} 

print(type(fruit_season))
print(fruit_season)


<class 'dict'>
{'raspberry': 'May', 'apple': 'September', 'peach': 'July', 'grape': 'August'}

To access a value, you index into it similarly to a list using square brackets.

value_of_key1 = my_dict['key1'] 

In [19]:
raspberry_season = fruit_season['raspberry']
print(raspberry_season)


May

Trying to access a key not in the dictionary throws an error


In [22]:
print(fruit_season['mangos'])


---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-22-8d98b83019d8> in <module>()
----> 1 print(fruit_season['mangos'])

KeyError: 'mangos'

To add an item to the dictionary set the value equal to the indexed keys

dict['new_key'] = value

In [23]:
fruit_season['strawberry'] = 'May'
print(fruit_season)


{'raspberry': 'May', 'apple': 'September', 'peach': 'July', 'grape': 'August', 'strawberry': 'May'}

In [26]:
fruit_season['strawberry']


---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-26-1c85e13ddc41> in <module>()
----> 1 fruit_season['strawberry']

KeyError: 'strawberry'

To delete a key, use the del keyword

del dict['key to delete']

In [25]:
del fruit_season['strawberry']
print(fruit_season)


{'raspberry': 'May', 'apple': 'September', 'peach': 'July', 'grape': 'August'}

Rules on keys

Keys in dictionary must be unique. If you try to make a duplicate key, the data will be overwritten

Keys must be hashable. What this means is they must come from immutable values and be comparable. You can use strings, numbers, tuples, sets, (most) objects. You cannot use lists or dictionaries as keys.


In [29]:
duplicate_fruit_season = {
    'raspberry': 'May',
    'raspberry': 'June',
} 
print(duplicate_fruit_season)


{'raspberry': 'June'}

In [30]:
mutable_key = {
    ['watermelon', 'cantaloupe', 'honeydew']: 'July'
}


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-30-97aea843dd8d> in <module>()
      1 mutable_key = {
----> 2     ['watermelon', 'cantaloupe', 'honeydew']: 'July'
      3 }

TypeError: unhashable type: 'list'

In [31]:
# The solution is to use a tuple instead
immutable_key = {
    ('watermelon', 'cantelope', 'honeydew'): 'July'
}

TRY IT

Create a dictionary called vegetable_season with Eggplant-> July and Onion -> May


In [34]:
vegetable_season = {
    'Eggplant': 'July',
    'Onion': 'May'
}
print(vegetable_season)


{'Eggplant': 'July', 'Onion': 'May'}

Dictionary Operators

The in operator returns a boolean for whether the key is in the dictionary or not.

key in dictionary 

In [35]:
print('raspberry' in fruit_season)
print('mangos' in fruit_season)


True
False

You can use this in if statement


In [37]:
if 'pineapple' in fruit_season:
    print('Lets eat tropical fruit')
else:
    print("Temperate fruit it is.")


Temperate fruit it is.

TRY IT

Check if 'broccoli' is in vegetable_season. If so, print 'Yum, little trees!'


In [39]:
if 'broccoli' in vegetable_season:
    print('Yum, little trees!')
else:
    print('No little trees.')


No little trees.

Dictionaries and Loops

You can use a for in loop to loop through dictionaries

for key in dictionary:
    print key

In [48]:
for fruit in fruit_season:
    print ("{0} is best in {1} (at least in Virginia)".format(fruit.title(), fruit_season[fruit]))


Raspberry is best in May (at least in Virginia)
Apple is best in September (at least in Virginia)
Peach is best in July (at least in Virginia)
Grape is best in August (at least in Virginia)

Dictionary Methods

You can use the keys, values, or items methods to return lists of keys, values, or key-value tuples respectively.

You can then use these for sorting or for looping


In [49]:
print(fruit_season.keys())
print(fruit_season.values())
print(fruit_season.items())


dict_keys(['raspberry', 'apple', 'peach', 'grape'])
dict_values(['May', 'September', 'July', 'August'])
dict_items([('raspberry', 'May'), ('apple', 'September'), ('peach', 'July'), ('grape', 'August')])

In [51]:
for key, value in fruit_season.items():
    print ("In {0} eat a {1}".format(value, key))


In May eat a raspberry
In September eat a apple
In July eat a peach
In August eat a grape

In [52]:
print (sorted(fruit_season.keys()))


['apple', 'grape', 'peach', 'raspberry']

TRY IT

Loop through the sorted keys of the vegetable_season dictionary. For each key, print the month it is in season


In [53]:
for fruit in sorted(fruit_season.keys()):
    print('In {0} {1} is in season.'.format(fruit_season[fruit], fruit))


In September apple is in season.
In August grape is in season.
In July peach is in season.
In May raspberry is in season.

More complex dictionaries

Dictionary keys and values can be almost anything. The keys must be hashable which means it cannot change. That means that lists and dictionaries cannot be keys (but strings, tuples, and integers can).

Values can be just about anything, though.


In [55]:
my_complicated_dictionary = {
    (1, 2, 3): 6,
    'weevil': {
        'e': 2,
        'i': 1,
        'l': 1,
        'v': 1,
        'w': 1,
    },
    9: [3, 3]
}
print (my_complicated_dictionary)


{(1, 2, 3): 6, 'weevil': {'e': 2, 'i': 1, 'l': 1, 'v': 1, 'w': 1}, 9: [3, 3]}

Let's use this to create a more realistic fruit season dictionary


In [56]:
true_fruit_season = {
    'raspberry': ['May', 'June'],
    'apple': ['September', 'October', 'November', 'December'],
    'peach': ['July', 'August'],
    'grape': ['August', 'September', 'October']
} 

print (true_fruit_season)


{'raspberry': ['May', 'June'], 'apple': ['September', 'October', 'November', 'December'], 'peach': ['July', 'August'], 'grape': ['August', 'September', 'October']}

In [58]:
months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']

for month in months:
    print ('It is {0}'.format(month))
    for fruit, season in true_fruit_season.items():
        if month in season:
            print ("\tEat {0}".format(fruit))


It is January
It is February
It is March
It is April
It is May
	Eat raspberry
It is June
	Eat raspberry
It is July
	Eat peach
It is August
	Eat peach
	Eat grape
It is September
	Eat apple
	Eat grape
It is October
	Eat apple
	Eat grape
It is November
	Eat apple
It is December
	Eat apple

TRY IT

Add a key to the true_fruit_season for 'watermelons' the season is July, August, and September


In [ ]:

Project: Acrostic

Create an acrostic poem generator.

You will create a function that takes a name and generates an acrostic poem

  1. Create a dictionary that has each of the capital letters as keys and an adjective that start with the letter as the value and store in variable named adjectives. (Reference: http://www.enchantedlearning.com/wordlist/adjectives.shtml)
  2. Create a function called "acrostic", which takes one parameter "name" as argument.
  3. In the acrostic function capitalize the name (use the upper method)
  4. For each letter in the name
    1. Get the adjective corresponding to that letter (from our dictionary) and store it in a variable called current_adj
    2. Print out Letter-current_adj

Challenge instead of just one adjective have each letter's value be a list of adjectives. Use the random module to select a random adjective instead of always selecting the same one.


In [39]:
from random import randint #necessary for "challenge"

# step 1: create dictionary with one adjective per letter of the alphabet
myadjectives = {
    'A':['admirable','aggressive','agile','agitated','agonizing','agreeable'],
    'B':'biodegradable',
    'C':['cloudy','creative'],
    'D':'deserted',
    'E':'everlasting',
    'F':'flamboyant',
    'G':'grotesque',
    'H':'humming',
    'I':'imperfect',
    'J':'joyful',
    'K':'kosher',
    'L':'lively',
    'M':'modest',
    'N':'nervous',
    'O':'ornate',
    'P':'playful',
    'Q':'quick',
    'R':['restless','relieved','remarkable','remorseful', 'remote'],
    'S':'strong',
    'T':'tiny',
    'U':'ugly',
    'V':'vital',
    'W':['wobbly','well-made'],
    'X':'oops!',
    'Y':'youthful',
    'Z':'zesty'
}

In [52]:
type(myadjectives['C'])


Out[52]:
list

In [53]:
# step 2: create funtion acrostic, takes name as an argument
def acrostic (name):
    # step 3: capitalize name
    capName = name.upper()
    
    # step 4
    for letter in capName:
        current_adj_list = myadjectives[letter]
        if type(current_adj_list) == list:
            current_adj = current_adj_list[randint(0,len(current_adj_list)-1)]
        else:
            current_adj = current_adj_list
        print("{0} - {1}".format(letter, current_adj))

In [56]:
acrostic('Lilly')


L - lively
I - imperfect
L - lively
L - lively
Y - youthful

Bonus Material

Auto generating the dictionary for the acrostic:


In [74]:
# If you have a list of adjectives
my_dict = {}

# Imaging this is the full alphabet
for i in ['A', 'B', 'C']:
    my_dict[i] = []
    
    
for i in ['Adoreable', 'Acceptable', 'Bad', 'Cute', 'Basic', 'Dumb','Active']:
    first_char = i[0]
    if first_char in my_dict:
        my_dict[first_char].append(i)
print (my_dict)


{'A': ['Adoreable', 'Acceptable', 'Active'], 'B': ['Bad', 'Basic'], 'C': ['Cute']}

In [62]:
# Generating from a file
my_dict = {}

for i in ['A', 'B', 'C']:
    my_dict[i] = []
    
# adjectives.txt has one adjective per line
with open('adjectives.txt') as fh:
    for line in fh:
        word = line.rstrip().title()
        first_char = word[0]
        if first_char in my_dict:
            my_dict[first_char].append(word)
            
print (my_dict['A'])


['Average', 'Ancient', 'Abundant', 'Afraid', 'Angry', 'Annoyed', 'Anxious', 'Arrogant', 'Ashamed', 'Awful', 'Agreeable', 'Amused', 'Able', 'Available', 'American', 'Appropriate', 'Aware', 'Annual', 'Additional', 'Active', 'Actual', 'Average', 'Afraid', 'Alone', 'Apparent', 'Attractive', 'Alternative', 'Ancient', 'Academic', 'African', 'Angry', 'Alive', 'Agricultural', 'Alright', 'Armed', 'Acceptable', 'Adequate', 'Administrative', 'Absolute', 'Advanced', 'Anxious', 'Awful', 'Accurate', 'Above', 'Asleep', 'Australian', 'Acute', 'Automatic', 'Arab']

In [ ]: