Day 4: Data Structures
What You'll Learn Today
- Lists: Ordered, mutable collections
- Tuples: Ordered, immutable collections
- Dictionaries: Key-value pairs
- Sets: Collections without duplicates
- List comprehensions
Lists
Lists are the most commonly used data structure for storing multiple values in order.
flowchart LR
subgraph List["List fruits"]
A["'apple'"] --> B["'banana'"] --> C["'cherry'"]
end
subgraph Index["Index"]
I0["0"] --> I1["1"] --> I2["2"]
end
style List fill:#3b82f6,color:#fff
Creating Lists
# Empty list
empty = []
also_empty = list()
# List with values
fruits = ["apple", "banana", "cherry"]
numbers = [1, 2, 3, 4, 5]
mixed = [1, "hello", 3.14, True] # Different types allowed
Accessing Elements
fruits = ["apple", "banana", "cherry", "date"]
# Access by index
print(fruits[0]) # apple (first)
print(fruits[2]) # cherry
print(fruits[-1]) # date (last)
print(fruits[-2]) # cherry (second to last)
Slicing
fruits = ["apple", "banana", "cherry", "date", "elderberry"]
print(fruits[1:4]) # ['banana', 'cherry', 'date']
print(fruits[:3]) # ['apple', 'banana', 'cherry']
print(fruits[2:]) # ['cherry', 'date', 'elderberry']
print(fruits[::2]) # ['apple', 'cherry', 'elderberry'] (every other)
print(fruits[::-1]) # Reversed
Modifying Lists
fruits = ["apple", "banana", "cherry"]
# Change element
fruits[1] = "blueberry"
print(fruits) # ['apple', 'blueberry', 'cherry']
# Add elements
fruits.append("date") # Add to end
fruits.insert(1, "apricot") # Insert at position
# Remove elements
fruits.remove("apple") # Remove by value
del fruits[0] # Remove by index
popped = fruits.pop() # Remove and return last item
popped = fruits.pop(0) # Remove and return item at index
Key List Methods
| Method | Description | Example |
|---|---|---|
append(x) |
Add to end | list.append(5) |
insert(i, x) |
Insert at position i | list.insert(0, 5) |
remove(x) |
Remove value x | list.remove(5) |
pop(i) |
Remove and return item at i | list.pop(0) |
index(x) |
Return index of x | list.index(5) |
count(x) |
Count occurrences of x | list.count(5) |
sort() |
Sort in place | list.sort() |
reverse() |
Reverse in place | list.reverse() |
copy() |
Return a copy | new = list.copy() |
clear() |
Remove all items | list.clear() |
Combining Lists
list1 = [1, 2, 3]
list2 = [4, 5, 6]
# Concatenate with +
combined = list1 + list2 # [1, 2, 3, 4, 5, 6]
# Extend in place
list1.extend(list2) # list1 becomes [1, 2, 3, 4, 5, 6]
# Repeat with *
repeated = [0] * 5 # [0, 0, 0, 0, 0]
Sorting Lists
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
# sort(): Modifies original list
numbers.sort()
print(numbers) # [1, 1, 2, 3, 4, 5, 6, 9]
numbers.sort(reverse=True)
print(numbers) # [9, 6, 5, 4, 3, 2, 1, 1]
# sorted(): Returns new list
original = [3, 1, 4, 1, 5]
sorted_list = sorted(original)
print(original) # [3, 1, 4, 1, 5] (unchanged)
print(sorted_list) # [1, 1, 3, 4, 5]
Tuples
Tuples are similar to lists but cannot be modified after creation (immutable).
# Creating tuples
coordinates = (10, 20)
rgb = (255, 128, 0)
single = (42,) # Single element requires comma
# Access (same as lists)
print(coordinates[0]) # 10
print(rgb[1:]) # (128, 0)
# Cannot modify
# coordinates[0] = 5 # TypeError!
Tuple Unpacking
# Assign to multiple variables at once
point = (3, 4)
x, y = point
print(x) # 3
print(y) # 4
# Return multiple values from function
def get_min_max(numbers):
return min(numbers), max(numbers)
minimum, maximum = get_min_max([3, 1, 4, 1, 5])
print(minimum, maximum) # 1 5
# Swap variables
a, b = 1, 2
a, b = b, a
print(a, b) # 2 1
Tuple vs List
| Property | Tuple | List |
|---|---|---|
| Mutable | ❌ | ✅ |
| Brackets | () |
[] |
| Use case | Fixed data | Variable data |
| Dict key | Can be used | Cannot be used |
| Speed | Faster | Slower |
Dictionaries (dict)
Dictionaries store data as key-value pairs.
flowchart TB
subgraph Dict["Dictionary person"]
K1["'name'"] --> V1["'Taro'"]
K2["'age'"] --> V2["25"]
K3["'city'"] --> V3["'Tokyo'"]
end
style Dict fill:#3b82f6,color:#fff
style K1 fill:#8b5cf6,color:#fff
style K2 fill:#8b5cf6,color:#fff
style K3 fill:#8b5cf6,color:#fff
style V1 fill:#22c55e,color:#fff
style V2 fill:#22c55e,color:#fff
style V3 fill:#22c55e,color:#fff
Creating Dictionaries
# Empty dictionary
empty = {}
also_empty = dict()
# Dictionary with values
person = {
"name": "Taro",
"age": 25,
"city": "Tokyo"
}
# Using dict()
person = dict(name="Taro", age=25, city="Tokyo")
Accessing Values
person = {"name": "Taro", "age": 25, "city": "Tokyo"}
# Access by key
print(person["name"]) # Taro
# Use get() (no error if key doesn't exist)
print(person.get("name")) # Taro
print(person.get("country")) # None
print(person.get("country", "Japan")) # Japan (default value)
Modifying Dictionaries
person = {"name": "Taro", "age": 25}
# Update value
person["age"] = 26
# Add new key
person["city"] = "Tokyo"
# Update multiple
person.update({"age": 27, "job": "Engineer"})
# Delete key
del person["city"]
removed = person.pop("age") # Get value and delete
Dictionary Methods
| Method | Description | Example |
|---|---|---|
get(key, default) |
Get value | d.get("name", "Unknown") |
keys() |
Return keys | d.keys() |
values() |
Return values | d.values() |
items() |
Return key-value pairs | d.items() |
pop(key) |
Remove and return value | d.pop("name") |
update(dict) |
Update dictionary | d.update({"a": 1}) |
clear() |
Remove all items | d.clear() |
Looping Through Dictionaries
person = {"name": "Taro", "age": 25, "city": "Tokyo"}
# Loop through keys
for key in person:
print(key)
# Loop through values
for value in person.values():
print(value)
# Loop through key-value pairs
for key, value in person.items():
print(f"{key}: {value}")
Checking for Keys
person = {"name": "Taro", "age": 25}
if "name" in person:
print("name key exists")
if "country" not in person:
print("country key doesn't exist")
Sets
Sets are collections of unique values (no duplicates).
flowchart TB
subgraph Set["Set numbers"]
A["1"]
B["2"]
C["3"]
D["4"]
E["5"]
end
style Set fill:#3b82f6,color:#fff
Creating Sets
# Empty set
empty = set() # Note: {} creates empty dict
# Set with values
numbers = {1, 2, 3, 4, 5}
fruits = {"apple", "banana", "cherry"}
# Create from list (removes duplicates)
numbers = set([1, 2, 2, 3, 3, 3])
print(numbers) # {1, 2, 3}
Set Operations
numbers = {1, 2, 3}
# Add
numbers.add(4)
print(numbers) # {1, 2, 3, 4}
# Remove
numbers.remove(2) # Error if not exists
numbers.discard(10) # No error if not exists
# Check membership
print(3 in numbers) # True
Set Theory Operations
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
# Union (in either set)
print(a | b) # {1, 2, 3, 4, 5, 6}
print(a.union(b))
# Intersection (in both sets)
print(a & b) # {3, 4}
print(a.intersection(b))
# Difference (in a but not b)
print(a - b) # {1, 2}
print(a.difference(b))
# Symmetric difference (in one but not both)
print(a ^ b) # {1, 2, 5, 6}
print(a.symmetric_difference(b))
flowchart LR
subgraph Union["Union a | b"]
U1["1, 2, 3, 4, 5, 6"]
end
subgraph Intersection["Intersection a & b"]
I1["3, 4"]
end
subgraph Difference["Difference a - b"]
D1["1, 2"]
end
style Union fill:#3b82f6,color:#fff
style Intersection fill:#22c55e,color:#fff
style Difference fill:#f59e0b,color:#fff
List Comprehensions
A concise way to create lists.
Basic Form
# Traditional approach
squares = []
for x in range(5):
squares.append(x ** 2)
print(squares) # [0, 1, 4, 9, 16]
# List comprehension
squares = [x ** 2 for x in range(5)]
print(squares) # [0, 1, 4, 9, 16]
With Condition
# Only squares of even numbers
even_squares = [x ** 2 for x in range(10) if x % 2 == 0]
print(even_squares) # [0, 4, 16, 36, 64]
# Using if-else
results = ["even" if x % 2 == 0 else "odd" for x in range(5)]
print(results) # ['even', 'odd', 'even', 'odd', 'even']
Nested Loops
# Multiplication table pairs
pairs = [(i, j) for i in range(1, 4) for j in range(1, 4)]
print(pairs)
# [(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)]
Dictionary Comprehension
# Numbers as keys, squares as values
squares = {x: x ** 2 for x in range(5)}
print(squares) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
Set Comprehension
# Set of squared values
squares = {x ** 2 for x in range(-3, 4)}
print(squares) # {0, 1, 4, 9} (duplicates removed)
Summary
| Data Structure | Brackets | Characteristics | Use Case |
|---|---|---|---|
| list | [] |
Ordered, mutable | General collections |
| tuple | () |
Ordered, immutable | Fixed data, dict keys |
| dict | {} |
Key-value pairs | Named data |
| set | {} |
No duplicates, unordered | Deduplication, set operations |
Key Takeaways
- Lists are the most versatile—add, remove, modify freely
- Tuples are immutable but can be used as dictionary keys
- Dictionaries access values by key (O(1) fast lookup)
- Sets automatically remove duplicates and support set operations
- Comprehensions make code more concise
Practice Exercises
Exercise 1: List Operations
Create a list of numbers 1-10 and extract only the even numbers into a new list.
Exercise 2: Dictionary
Create a dictionary with 5 people's names and ages, then calculate and display the average age.
Challenge
Write a program using sets to find the common elements and unique elements between two lists.
list1 = [1, 2, 3, 4, 5]
list2 = [4, 5, 6, 7, 8]
# Common: [4, 5]
# Only in list1: [1, 2, 3]
# Only in list2: [6, 7, 8]
References
Next Up: In Day 5, you'll learn about "Functions." Organize your code into reusable pieces!