Dictionary type
Contents
18. Dictionary type#
Author: Tue Nguyen
18.1. Outline#
What is a dictionary?
Create a dictionary
Elements of a dict
Iterate through a dictionary
Copy a dictionary
Operations on dictionaries
Dict comprehensions
18.2. What is a dictionary?#
A dictionary (or dict) is used to store data in the form of
key: valuepairsEach element of a dict is has a
keypart and avaluepartElements are accessed using
keyDicts are mutable
The keys must be unique and of an immutable type
However, the values can be of any types
For Python
<= 3.6, dicts are not orderedFor Python
>= 3.7, dicts are insertion ordered
18.3. Create a dict#
18.3.1. Use {}#
# A dict with one element
d = {"name": "John"}
print(d)
print(type(d))
{'name': 'John'}
<class 'dict'>
# For a dict with multi elements
# We can span more than 1 line for readability
d = {
"name": "John",
"age": 20,
"country": "UK"
}
print(d)
{'name': 'John', 'age': 20, 'country': 'UK'}
18.3.2. Use dict()#
d = dict(
name="John",
age=20,
country="UK"
)
print(d)
{'name': 'John', 'age': 20, 'country': 'UK'}
18.4. Elements of a dict#
18.4.1. Keys, values, and items#
# Recall the dict
d
{'name': 'John', 'age': 20, 'country': 'UK'}
# Get keys
d.keys()
dict_keys(['name', 'age', 'country'])
# Get values
d.values()
dict_values(['John', 20, 'UK'])
# View elements as a sequence of tuples
# Keys are the first elements in the tuples
# We usually use this when iterate through a list
d.items()
dict_items([('name', 'John'), ('age', 20), ('country', 'UK')])
18.4.2. Get values by keys#
# Get value associated with name
d["name"]
'John'
# Get value associated with country
d["country"]
'UK'
18.4.3. Add and update elements#
We use assignment to add a new elements or update the value for an exisiting element
# Init
d = {"name": "John", "age": 20}
d
{'name': 'John', 'age': 20}
# Add education
d["educ"] = "BSc"
d
{'name': 'John', 'age': 20, 'educ': 'BSc'}
# Now update education to MSc
d["educ"] = "MSc"
d
{'name': 'John', 'age': 20, 'educ': 'MSc'}
18.5. Dict keys#
a) Dict keys must be of immutable types
# Int keys
{1: True, 2: "A"}
{1: True, 2: 'A'}
# Float keys are possible but not recommended
# Because computer store floats approximately
{1.2: True, 5.: "B"}
{1.2: True, 5.0: 'B'}
# String keys
{"name": "John", "age": 20}
{'name': 'John', 'age': 20}
# Tuple keys
d = {
("US", "gdp"): 19.49,
("US", "pop"): 325,
("CN", "gdp"): 12.24,
("CN", "pop"): 1421
}
print(d[("US", "gdp")]) # GDF of US
print(d[("CN", "pop")]) # Population of china
19.49
1421
b) Dict keys must be unique
# Try to duplicate a key, only the latter is kept
{"name": "John", "age": 20, "age": 30}
{'name': 'John', 'age': 30}
18.6. Conversion to dicts#
We use dict() to convert an object to a dict
# Convert a sequence of 2-element squences
data = [("name", "John"), ("age", 20)]
dict(data)
{'name': 'John', 'age': 20}
# Convert a zipped object to a dict
names = ["A", "B"]
ages = [20, 30]
dict(zip(names, ages))
{'A': 20, 'B': 30}
18.7. Iterate through a dict#
# Init a dict
d = {"name": "John", "age": 20, "educ": "MSc"}
d
{'name': 'John', 'age': 20, 'educ': 'MSc'}
18.7.1. Iterate through keys#
# Method 1
for k in d:
print(k)
name
age
educ
# Method 2
for k in d.keys():
print(k)
name
age
educ
18.7.2. Iterate through values#
for v in d.values():
print(v)
John
20
MSc
18.7.3. Iterate through both keys and values#
# Naive way
for k in d:
print(f"Key {k} has value {d[k]}")
Key name has value John
Key age has value 20
Key educ has value MSc
# Better way
for k, v in d.items():
print(f"Key {k} has value {v}")
Key name has value John
Key age has value 20
Key educ has value MSc
What happened?
Recall that each element of
d.items()is 2-element tupleThus writing
k, vin the for loop means we unpack the corresponding tuple at each iterationThus the key goes to
kand the value goes tov
18.8. Mutablity#
A dict is mutable
We can add, update, or delete elements
18.9. Copy a dict#
Since the dict type is mutable, copying a dict has the same behavior as copying a list
18.9.1. Shallow copying#
# Init a dict
d = {"name": "John", "degrees": ["BSc", "MSc"]}
print(d)
print(id(d))
{'name': 'John', 'degrees': ['BSc', 'MSc']}
139923067098176
# Make a shallow copy
d2 = d.copy()
# Verify d and d2 have the same values
print(d)
print(d2)
print(d == d2)
{'name': 'John', 'degrees': ['BSc', 'MSc']}
{'name': 'John', 'degrees': ['BSc', 'MSc']}
True
# But d and d2 are pointing to different objects
print(id(d))
print(id(d2))
print(d is d2)
139923067098176
139923101568704
False
# Changing name of d (a string - immutable)
# will not change name of d2
d["name"] = "Jack"
print(d)
print(d2)
{'name': 'Jack', 'degrees': ['BSc', 'MSc']}
{'name': 'John', 'degrees': ['BSc', 'MSc']}
# But modifying degrees of d (a list - mutable)
# will also modify that of d2
d["degrees"][0] = "PhD"
print(d)
print(d2)
{'name': 'Jack', 'degrees': ['PhD', 'MSc']}
{'name': 'John', 'degrees': ['PhD', 'MSc']}
18.9.2. Deep copying#
Same as lists, we use copy.deepcopy()
# Init
d = {"name": "John", "degrees": ["BSc", "MSc"]}
d
{'name': 'John', 'degrees': ['BSc', 'MSc']}
# Import module copy
import copy
# Make a deep copy
d2 = copy.deepcopy(d)
# Change degrees of d, d2 stays the same
d["degrees"][0] = "PhD"
print(d)
print(d2)
{'name': 'John', 'degrees': ['PhD', 'MSc']}
{'name': 'John', 'degrees': ['BSc', 'MSc']}
18.10. Operations on a dict#
As a mutable type like lists, we also have two types of operations on dicts
Regular operations
Inplace operations
18.10.1. Regular operations#
# Init a dict
d = {"name": "John", "age": 20, "educ": "BSc"}
d
{'name': 'John', 'age': 20, 'educ': 'BSc'}
Get value by key
# Traditional way
d["name"]
'John'
# However, if the key is not in d, we will get an error
# Try d["weight"]
# To avoid an error, we can use .get
# If the key is not in d, we will get a None back
w = d.get("weight")
print(w)
None
# If we don't like None, we can set the default value
d.get("weight", "N/A")
'N/A'
Count number of elements
len(d)
3
Member ship checking
# Check if d has a key "age"
"age" in d
True
# Check if d has a key "address"
"address" in d
False
# Check if d has a value 20
20 in d.values()
True
18.10.2. Inplace operations#
# Init a dict
d = {"name": "John", "age": 20, "educ": "BSc"}
d
{'name': 'John', 'age': 20, 'educ': 'BSc'}
Add or update elements
# Add country
d["country"] = "UK"
d
{'name': 'John', 'age': 20, 'educ': 'BSc', 'country': 'UK'}
# Update country to "US"
d["country"] = "US"
d
{'name': 'John', 'age': 20, 'educ': 'BSc', 'country': 'US'}
Delete an element
# Use del to delete by key
del d["country"]
d
{'name': 'John', 'age': 20, 'educ': 'BSc'}
# However, if key is not in d, we will get an error
# Try del d["weight"] to see it
# We can use an if statement to avoid this
if "weight" in d:
del d["weight"]
d
{'name': 'John', 'age': 20, 'educ': 'BSc'}
Set default
Sometimes, we are not sure if a key already exists
If it exists, we want to leave it as it is
If not, we want to add a new element with the key and a default value
# Init a dict
d = {"name": "John", "age": 20, "educ": "BSc"}
d
{'name': 'John', 'age': 20, 'educ': 'BSc'}
# If key "age" exists, leave it as it is
# If not, add a new element with that key and value -1
d.setdefault("age", -1)
d
{'name': 'John', 'age': 20, 'educ': 'BSc'}
# If key "credits" exists, leave it as it is
# If not, add a new element with that key and value 0
d.setdefault("credits", 0)
d
{'name': 'John', 'age': 20, 'educ': 'BSc', 'credits': 0}
Pop an element
# We can pop a value by key
# Also note that if the key is not in d, we will get an error
educ = d.pop("educ")
print(educ)
print(d)
BSc
{'name': 'John', 'age': 20, 'credits': 0}
Update a dict
# Init 2 dict
d = {"name": "John", "age": 20}
d2 = {"age": 22, "educ": "BSc"}
print(d)
print(d2)
{'name': 'John', 'age': 20}
{'age': 22, 'educ': 'BSc'}
# Update d with info from d2
# Key "educ" is new to d -> new element is created for this key
# Key "age" already exists in d -> update the value for this key from d2
d.update(d2)
d
{'name': 'John', 'age': 22, 'educ': 'BSc'}
18.11. Dict comprehensions#
Dict comprehensions are similar to list comprehensions
Used to quickly make a dict from an iterable
Syntax 1 (without filtering):
{key_expr: value_expr for item in iterable}Syntax 2 (with filtering):
{key_expr: value_expr for item in iterable if condition}
# Make a dict from a list of words
# Keys are words in lowercase
# Values are words in uppercase
words = ["Cat", "Dog", "Cow", "Duck"]
{w.lower(): w.upper() for w in words}
{'cat': 'CAT', 'dog': 'DOG', 'cow': 'COW', 'duck': 'DUCK'}
# From list words above, make a dict
# Keys are the position of the word
# Value are the words themselves
{(i+1): v for i, v in enumerate(words)}
{1: 'Cat', 2: 'Dog', 3: 'Cow', 4: 'Duck'}
# Make a dict
# Keys are integers from 1 to 5
# Values are squares of keys
{v:v**2 for v in range(1, 6)}
{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# From list words above, make a list
# Keys are words
# Values are the numbers of characters
# Only keep words with <= 3 characters
{w: len(w) for w in words if len(w) <= 3}
{'Cat': 3, 'Dog': 3, 'Cow': 3}
18.12. Summary#
What is a dictionary?
Mutable object storing data in the form of
key: valuepairsEach element of a dict is has a
keypart and avaluepartElements are accessed using
keyThe keys must be unique and of an immutable type
However, the values can be of any types
For Python
<= 3.6, dicts are not orderedFor Python
>= 3.7, dicts are insertion ordered
Create a dict
Use
{}ordict()
Iterate through a dictionary
Iterate through keys:
for k in dIterate through values:
for v in d.values()Iterate through items:
for k, v in d.items()
Copy a dictionary
Same as lists (there are both shallow and deep copying)
Operations on dicts
Regular operations
Get value by key:
d["name"],d.get("name")Count number of elements:
len(d)Membership checking:
"name" in d,"John" in d.values()
Inplace operations
Add or update an element:
d["name"] = "Jack"Delete an element:
del d["name"]Set default:
d.setdefault("name", "N/A")Pop an element:
name = d.pop("name")Update a dict:
d.update(d2)
Dict comprehensions
Similar to list comprehensions
Syntax 1:
{key_expr: value_expr for item in iterable}Syntax 2:
{key_expr: value_expr for item in iterable if condition}
18.13. Practice#
To be updated