Python Concepts/Dictionaries
Objective
[edit | edit source]
|
Page Index
[edit | edit source]Lesson
[edit | edit source]
Python dictionaries are (apparently) random sequences that contain a set of keys, where each key points to a value and is associated with that value, hence the expression "associative arrays" sometimes found in other languages. Dictionaries act just like real life dictionaries, where the key is the word and the value is the word's definition.
>>> {"blue": 0, "red": 1, "green": 2} #
{'green': 2, 'red': 1, 'blue': 0} # Ordering is different from that supplied above.
# "blue" is a key. Its associated value is 0.
# "red" is a key. Its associated value is 1.
# "green" is a key. Its associated value is 2.
>>>
>>> {"blue": 0, "red": 1, "green": 2} == {"green": 2, "blue": 0, "red": 1} == {"green": 2, "red": 1, "blue": 0}
True # Ordering is not important.
>>>
>>> isinstance( {"green": 2, "blue": 0, "red": 1}, dict )
True
>>>
>>> {30: "0", 31: "1", "32": 2}
{'32': 2, 30: '0', 31: '1'}
>>>
>>> isinstance({}, dict)
True
>>> isinstance({}, set)
False
|
Basic operations on dictionaries
[edit | edit source]
>>> # create dictionary phoneNumbers
>>> phoneNumbers = {}
>>>
>>> # add entries to phoneNumbers
>>> phoneNumbers['Jack'] = 1234
>>> phoneNumbers['Bill'] = 2234
>>> phoneNumbers['andy'] = 2235
>>>
>>> # display contents of phoneNumbers
>>> phoneNumbers
{'Jack': 1234, 'Bill': 2234, 'andy': 2235}
>>>
>>> # there is a typo in 'andy'
>>> del phoneNumbers['andy']
>>> phoneNumbers
{'Jack': 1234, 'Bill': 2234}
>>>
>>> # correct entry for 'Andy'
>>> phoneNumbers['Andy'] = 2235
>>> phoneNumbers
{'Jack': 1234, 'Bill': 2234, 'Andy': 2235}
>>>
>>> # query the dictionary
>>> 'George' in phoneNumbers
False
>>> 'Bill' in phoneNumbers
True
>>> 2235 in phoneNumbers
False # True is returned only for keys.
>>>
>>> phoneNumbers['Bill']
2234
>>> phoneNumbers['George']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'George'
>>>
>>> # if you wish to handle a possible error:
>>> status = 'Bill' in phoneNumbers and print (phoneNumbers['Bill']) ; status
2234
>>> status = 'George' in phoneNumbers and print (phoneNumbers['George']) ; status
False
>>>
>>> # better:
>>> phoneNumbers = {'Jack': 1234, 'George': 2235, 'Susie': 1231}
>>> for name in ('Bill', 'George') :
... if name in phoneNumbers : print ("{}'s".format(name), 'phone number is', phoneNumbers[name])
... else : print ("No entry for", name)
...
No entry for Bill
George's phone number is 2235
>>>
|
Dictionary views
[edit | edit source]
The objects returned by Values not unique: >>> phoneNumbers
{'Jack': 1234, 'Bill': 2234, 'Andy': 2235}
>>> phoneNumbers['George'] = 2235 # same as Andy
>>> phoneNumbers
{'Jack': 1234, 'Bill': 2234, 'Andy': 2235, 'George': 2235}
>>>
Retrieve the keys: >>> [*phoneNumbers]
['Jack', 'Bill', 'Andy', 'George']
>>>
>>> names = list(phoneNumbers) ; names
['Jack', 'Bill', 'Andy', 'George']
>>>
>>> names = phoneNumbers.keys() ; names
dict_keys(['Jack', 'Bill', 'Andy', 'George'])
>>> 'Jack' in phoneNumbers
True
>>> 'Jack' in phoneNumbers.keys()
True
>>> name = 'Jack' ; (name in phoneNumbers) == (name in phoneNumbers.keys())
True
>>> name = 'Linda' ; (name in phoneNumbers) == (name in phoneNumbers.keys()) # False == False
True
>>>
>>> # the keys are all unique, similar to a set.
>>> set(names)
{'Bill', 'George', 'Andy', 'Jack'}
>>> len(names) == len(set(names))
True # always
>>> names & {'Andy', 'George', 'Linda', 'Susie'}
{'Andy', 'George'} # keys behave like a set
>>>
Retrieve the values >>> numbers = phoneNumbers.values() ; numbers
dict_values([1234, 2234, 2235, 2235]) # not all unique
>>> set(numbers)
{2234, 1234, 2235}
>>> len(numbers) == len(set(numbers))
False # usually
>>>
>>> 2235 in phoneNumbers.values()
True
>>> 2335 in phoneNumbers.values()
False
>>>
Retrieve keys and values as a sequence of (key,value) pairs where each pair is a tuple >>> pairs = phoneNumbers.items() ; pairs
dict_items([('Jack', 1234), ('Bill', 2234), ('Andy', 2235), ('George', 2235)])
>>> len(pairs)
4
>>>
>>> pairs = list(phoneNumbers.items()) ; pairs
[('Jack', 1234), ('Bill', 2234), ('Andy', 2235), ('George', 2235)]
>>> isinstance(pairs[0], tuple)
True
>>>
>>> pairs = tuple(phoneNumbers.items()) ; pairs
(('Jack', 1234), ('Bill', 2234), ('Andy', 2235), ('George', 2235))
>>> isinstance(pairs[2], tuple)
True
>>>
>>> ('Andy', 2235) in phoneNumbers.items()
True
>>> ('Ted', 2235) in phoneNumbers.items()
False
>>> ('Andy', 2236) in phoneNumbers.items()
False
>>> ['Andy', 2235] in phoneNumbers.items()
False
>>> tuple(['Andy', 2235]) in phoneNumbers.items()
True
>>>
Views are dynamic: >>> phoneNumbers
{'Jack': 1234, 'Bill': 2234, 'George': 2235, 'Ted': 1245, 'Susie': 1231}
>>> names = phoneNumbers.keys() ; names
dict_keys(['Jack', 'Bill', 'George', 'Ted', 'Susie'])
>>> numbers = phoneNumbers.values() ; numbers
dict_values([1234, 2234, 2235, 1245, 1231])
>>> pairs = phoneNumbers.items() ; pairs
dict_items([('Jack', 1234), ('Bill', 2234), ('George', 2235), ('Ted', 1245), ('Susie', 1231)])
>>>
>>> del phoneNumbers['Ted']
>>> names; numbers ; pairs # all reflect the change (like shallow copies)
dict_keys(['Jack', 'Bill', 'George', 'Susie'])
dict_values([1234, 2234, 2235, 1231])
dict_items([('Jack', 1234), ('Bill', 2234), ('George', 2235), ('Susie', 1231)])
>>>
>>> phoneNumbers['Frank'] = 2233
>>> names; numbers ; pairs # all reflect the change (like shallow copies)
dict_keys(['Jack', 'Bill', 'George', 'Susie', 'Frank'])
dict_values([1234, 2234, 2235, 1231, 2233])
dict_items([('Jack', 1234), ('Bill', 2234), ('George', 2235), ('Susie', 1231), ('Frank', 2233)])
>>>
>>> # for a deep copy:
>>> pairs = tuple(phoneNumbers.items()) ; pairs
(('Jack', 1234), ('Bill', 2234), ('George', 2235), ('Susie', 1231), ('Frank', 2233))
>>>
>>> del phoneNumbers['Bill']
>>> phoneNumbers
{'Jack': 1234, 'George': 2235, 'Susie': 1231, 'Frank': 2233}
>>>
>>> pairs
(('Jack', 1234), ('Bill', 2234), ('George', 2235), ('Susie', 1231), ('Frank', 2233)) # like a deep copy
>>>
Iterations over keys, values, items: >>> phoneNumbers
{'Jack': 1234, 'George': 2235, 'Susie': 1231, 'Frank': 2233}
>>>
>>> names = []
>>> for name in phoneNumbers.keys() : names += [name]
...
>>> names
['Jack', 'George', 'Susie', 'Frank']
>>>
>>> numbers = []
>>> for number in phoneNumbers.values() : numbers += [number]
...
>>> numbers
[1234, 2235, 1231, 2233]
>>>
>>> data = []
>>> for (key, value) in phoneNumbers.items() : data += [(key, value)]
...
>>> data
[('Jack', 1234), ('George', 2235), ('Susie', 1231), ('Frank', 2233)]
>>>
Summary: >>> len(phoneNumbers.items())==len(phoneNumbers.keys())==len(phoneNumbers.values())
True # always
>>>
>>> phoneNumbers
{'Jack': 1234, 'Bill': 2234, 'Andy': 2235, 'George': 2235}
>>> data
(('Andy', 1244), ('Ted', 1245), ('Linda', 1230), ('Susie', 1231))
>>> for (name, number) in data : phoneNumbers[name] = number # update phoneNumbers
...
>>> phoneNumbers # Andy's number has changed
{'Jack': 1234, 'Bill': 2234, 'Andy': 1244, 'George': 2235, 'Ted': 1245, 'Linda': 1230, 'Susie': 1231}
>>>
>>> # iteration over keys, iteration over values, iteration over items
>>> # are always in same order.
>>> list(phoneNumbers.keys())
['Jack', 'Bill', 'Andy', 'George', 'Ted', 'Linda', 'Susie']
>>> list(phoneNumbers.items())
[('Jack', 1234), ('Bill', 2234), ('Andy', 1244), ('George', 2235), ('Ted', 1245), ('Linda', 1230), ('Susie', 1231)]
>>> list(phoneNumbers.values())
[1234, 2234, 1244, 2235, 1245, 1230, 1231]
>>>
|
Other operations on dictionaries
[edit | edit source]
>>> names
['Jack', 'George', 'Susie', 'Frank']
>>> numbers
[ 1234, 2235, 1231, 2233] # each number corresponds to a name above:
>>> list(zip(names, numbers))
[('Jack', 1234), ('George', 2235), ('Susie', 1231), ('Frank', 2233)]
>>>
[edit | edit source] |
An elementary database
[edit | edit source]
friends = {}
The information which we'd like to include is: name, age, address, phone number, hobbies. Add entries to "friends:" friends['Bill'] = [22, 'Black Street', 1234, [None]]
friends['Alan'] = [20, 'Brown Street', 2345, ['cycling','stamp collecting']]
friends['Tim'] = [19, 'Green Street', 3456, ['parachuting', 'video games','athletics']]
friends['Linda'] = [19, 'Brown Street', 4567, ['old movies']]
friends['Jenny'] = [21, 'Grey Street', 4567, ['old movies', 'cycling', 'video games', 'genealogy']]
Access the data in the database: print ("Bill's age is", friends['Bill'][0])
print ("Alan's address is", friends['Alan'][1])
print ("Tim's phone number is", friends['Tim'][2])
print ("Linda's hobbies are", friends['Linda'][3])
print ("Jenny's hobbies are", friends['Jenny'][3])
Bill's age is 22 Alan's address is Brown Street Tim's phone number is 3456 Linda's hobbies are ['old movies'] Jenny's hobbies are ['old movies', 'cycling', 'video games', 'genealogy']
age = 0; address = 1; phoneNumber = 2; hobbies = 3
print ("Bill's age is", friends['Bill'][age])
print ("Alan's address is", friends['Alan'][address])
print ("Tim's phone number is", friends['Tim'][phoneNumber])
print ("Linda's hobbies are", friends['Linda'][hobbies])
print ("Jenny's hobbies are", friends['Jenny'][hobbies])
Output is same as above. Make the output of 'hobbies' more readable: for name in list(friends) :
d = friends[name][hobbies]
if d :
if len(d) == 1 :
if d[0] == None:
print ('Nothing for', name, "under 'hobbies'.")
else :
print("{}'s hobby is: {}.".format( name, d[0] ))
else:
s = "{}'s hobbies are: {}".format( name, d[0] )
for k in range(1,len(d)):
s += ", {}".format(d[k])
s += '.'
print (s)
else:
print ('No info for', name, "under 'hobbies'.")
Nothing for Bill under 'hobbies'. Alan's hobbies are: cycling, stamp collecting. Tim's hobbies are: parachuting, video games, athletics. Linda's hobby is: old movies. Jenny's hobbies are: old movies, cycling, video games, genealogy.
friends['Bill'] += [[ ['Ford','classic', 1948, ['v8','ohv','water-cooled']], 'Ford' ]]
friends['Alan'] += [[]]
friends['Tim'] += [['Toyoya','Chevy']]
friends['Linda'] += [['Volvo']]
friends['Jenny'] += [['Subaru']]
Check the additional data: for name in friends : print (name, friends[name][-1])
Bill [['Ford', 'classic', 1948, ['v8', 'ohv', 'water-cooled']], 'Ford'] Alan [] Tim ['Toyoya', 'Chevy'] Linda ['Volvo'] Jenny ['Subaru'] This is a simple database and already it's becoming complicated: cars = 4
print (friends['Bill'][cars][0][1])
print (friends['Bill'][cars][0][3][2])
classic water-cooled
friends['Tim'][phoneNumber] = [ ['cell', number], ['home', number], ['business', number, extension] ]
Fortunately, python's list processing capabilities are powerful and almost unlimited.
for name in list(friends) :
if friends[name][address] == 'Brown Street' :
print (name, 'lives on Brown Street.')
Alan lives on Brown Street. Linda lives on Brown Street.
for name in list(friends) :
d = friends[name][hobbies]
for hobby in d :
if hobby == 'video games' :
print (name, 'enjoys video games.')
Tim enjoys video games. Jenny enjoys video games.
for name in friends :
autoInfo = friends[name][4]
for item in autoInfo:
if (isinstance(item, list)) and (isinstance(item[3], list)) :
if ('classic' in item) and ('ohv' in item[3]) :
print (name, 'has one.')
Bill has one. Integrity of the database
If you see a friend's age as 112, would this make sense? In a multi-item cell like "hobbies" remove duplicates: Does a list like Would you keep a hobby like 'robbing banks' in your database?
|
Assignments
[edit | edit source]
|
|
References
[edit | edit source]1. Python's documentation:
"Dictionaries", "Displays for lists, sets and dictionaries", "Dictionary displays", "Dictionary Objects", "4.10. Mapping Types — dict", "4.10.1. Dictionary view objects", "4.7.2. Keyword Arguments", "How are dictionaries implemented?", "Why must dictionary keys be immutable?"
2. Python's methods:
3. Python's built-in functions: