Dev In The Mountain Header
A Developer In The mountains having fun

Dictionaries and Sets in Python

Dictionaries and sets are powerful data structures that solve common programming problems efficiently. Dictionaries store key-value pairs for fast lookups, while sets store unique values and perform set operations. Both are essential tools in every Python programmer's toolkit.

What are Dictionaries?

A dictionary is an unordered collection of key-value pairs. Each key must be unique and maps to a value.

# Creating dictionaries
student = {
    'name': 'Alice',
    'age': 20,
    'grade': 'A',
    'gpa': 3.8
}

# Access values by key
print(student['name'])  # 'Alice'
print(student['gpa'])   # 3.8

# Empty dictionary
empty_dict = {}
empty_dict2 = dict()

Key Characteristics

  • Unordered: No guaranteed order (Python 3.7+ maintains insertion order)
  • Mutable: Can add, modify, or remove items
  • Keys must be immutable: strings, numbers, tuples (not lists)
  • Values can be anything: any data type
  • Fast lookups: O(1) average time complexity

Creating Dictionaries

# Direct assignment
person = {'name': 'Bob', 'age': 30}

# Using dict() constructor
person = dict(name='Bob', age=30)

# From list of tuples
pairs = [('name', 'Charlie'), ('age', 25)]
person = dict(pairs)

# Dictionary comprehension
squares = {x: x**2 for x in range(6)}
print(squares)  # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

# From two lists using zip
keys = ['name', 'age', 'city']
values = ['Diana', 28, 'Paris']
person = dict(zip(keys, values))

Accessing Dictionary Values

student = {'name': 'Alice', 'age': 20, 'grade': 'A'}

# Using square brackets
name = student['name']

# Using get() method (safer - returns None if key doesn't exist)
age = student.get('age')
email = student.get('email')  # Returns None
email = student.get('email', 'not provided')  # Custom default

# Check if key exists
if 'grade' in student:
    print(f"Grade: {student['grade']}")

if 'email' not in student:
    print("No email on file")

Modifying Dictionaries

student = {'name': 'Bob', 'age': 20}

# Add new key-value pair
student['email'] = 'bob@email.com'
student['gpa'] = 3.5

# Modify existing value
student['age'] = 21

# Update multiple items
student.update({'grade': 'B', 'major': 'CS'})

# Remove items
del student['email']  # Remove by key
gpa = student.pop('gpa')  # Remove and return value
student.popitem()  # Remove and return last item

# Clear all items
student.clear()

Dictionary Methods

person = {'name': 'Alice', 'age': 25, 'city': 'NYC'}

# keys(), values(), items()
print(person.keys())    # dict_keys(['name', 'age', 'city'])
print(person.values())  # dict_values(['Alice', 25, 'NYC'])
print(person.items())   # dict_items([('name', 'Alice'), ...])

# Convert to lists
keys_list = list(person.keys())
values_list = list(person.values())

# setdefault(): Get value or set if doesn't exist
email = person.setdefault('email', 'default@email.com')

# copy(): Create shallow copy
person_copy = person.copy()

Looping Through Dictionaries

grades = {'Alice': 85, 'Bob': 92, 'Charlie': 78}

# Loop through keys
for name in grades:
    print(name)

# Loop through keys explicitly
for name in grades.keys():
    print(name)

# Loop through values
for grade in grades.values():
    print(grade)

# Loop through key-value pairs
for name, grade in grades.items():
    print(f"{name}: {grade}")

# With enumerate
for index, (name, grade) in enumerate(grades.items()):
    print(f"{index}: {name} = {grade}")

Nested Dictionaries

# Dictionary of dictionaries
students = {
    'student1': {'name': 'Alice', 'age': 20, 'gpa': 3.8},
    'student2': {'name': 'Bob', 'age': 21, 'gpa': 3.5},
    'student3': {'name': 'Charlie', 'age': 19, 'gpa': 3.9}
}

# Access nested values
print(students['student1']['name'])  # 'Alice'

# Loop through nested dict
for student_id, info in students.items():
    print(f"{student_id}:")
    for key, value in info.items():
        print(f"  {key}: {value}")

# Add to nested dictionary
students['student4'] = {'name': 'Diana', 'age': 20, 'gpa': 4.0}

Dictionary Comprehensions

# Create dictionary from expression
squares = {x: x**2 for x in range(6)}

# Filter with condition
even_squares = {x: x**2 for x in range(10) if x % 2 == 0}

# Transform existing dict
temps_celsius = {'morning': 20, 'noon': 25, 'evening': 22}
temps_fahrenheit = {time: (temp * 9/5) + 32 
                   for time, temp in temps_celsius.items()}

# Create dict from two lists
names = ['Alice', 'Bob', 'Charlie']
ages = [20, 21, 19]
students = {name: age for name, age in zip(names, ages)}

What are Sets?

A set is an unordered collection of unique items.

# Creating sets
fruits = {'apple', 'banana', 'cherry'}
numbers = {1, 2, 3, 4, 5}

# Sets automatically remove duplicates
numbers = {1, 2, 2, 3, 3, 3}
print(numbers)  # {1, 2, 3}

# Empty set (must use set(), not {})
empty_set = set()

# Create from list
my_list = [1, 2, 2, 3, 3, 3]
unique = set(my_list)
print(unique)  # {1, 2, 3}

Key Characteristics

  • Unordered: No indexing or order
  • Unique: No duplicate values
  • Mutable: Can add/remove items
  • Items must be immutable: no lists or dicts as elements
  • Fast membership testing: O(1) average

Set Operations

# Add and remove
fruits = {'apple', 'banana'}
fruits.add('cherry')
fruits.add('apple')  # No effect - already exists

fruits.remove('banana')  # Raises error if not found
fruits.discard('orange')  # No error if not found

fruits.pop()  # Remove arbitrary element
fruits.clear()  # Remove all

# Membership testing
if 'apple' in fruits:
    print("We have apples")

Mathematical Set Operations

set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}

# Union (all elements from both)
union = set1 | set2  # or set1.union(set2)
print(union)  # {1, 2, 3, 4, 5, 6, 7, 8}

# Intersection (common elements)
intersection = set1 & set2  # or set1.intersection(set2)
print(intersection)  # {4, 5}

# Difference (in set1 but not set2)
difference = set1 - set2  # or set1.difference(set2)
print(difference)  # {1, 2, 3}

# Symmetric difference (in either but not both)
sym_diff = set1 ^ set2  # or set1.symmetric_difference(set2)
print(sym_diff)  # {1, 2, 3, 6, 7, 8}

# Subset and superset
set_a = {1, 2, 3}
set_b = {1, 2, 3, 4, 5}

print(set_a.issubset(set_b))    # True
print(set_b.issuperset(set_a))  # True
print(set_a.isdisjoint(set_b))  # False (have common elements)

Practical Examples

Example 1: Word Frequency Counter

text = "the quick brown fox jumps over the lazy dog the fox"
words = text.split()

# Count word frequencies
word_count = {}
for word in words:
    word_count[word] = word_count.get(word, 0) + 1

print("Word frequencies:")
for word, count in word_count.items():
    print(f"{word}: {count}")

# Using Counter from collections
from collections import Counter
word_count = Counter(words)
print(word_count.most_common(3))  # Top 3 words

Example 2: Student Grade Book

# Store student grades
gradebook = {
    'Alice': [85, 92, 78, 90],
    'Bob': [75, 88, 82, 86],
    'Charlie': [95, 89, 93, 91]
}

# Calculate averages
print("Student Averages:")
for student, grades in gradebook.items():
    average = sum(grades) / len(grades)
    print(f"{student}: {average:.1f}")

# Add new grade
gradebook['Alice'].append(88)

# Find top student
best_student = max(gradebook.items(), 
                  key=lambda x: sum(x[1])/len(x[1]))
print(f"\nTop student: {best_student[0]}")

Example 3: Remove Duplicates While Preserving Order

# Using dict (Python 3.7+)
def remove_duplicates(items):
    return list(dict.fromkeys(items))

numbers = [1, 2, 3, 2, 4, 3, 5, 1]
unique = remove_duplicates(numbers)
print(unique)  # [1, 2, 3, 4, 5]

Example 4: Find Common and Unique Elements

# Students in two classes
class_a = {'Alice', 'Bob', 'Charlie', 'Diana'}
class_b = {'Charlie', 'Diana', 'Eve', 'Frank'}

# Students in both classes
both = class_a & class_b
print(f"In both classes: {both}")

# Students in only one class
only_a = class_a - class_b
only_b = class_b - class_a
print(f"Only in A: {only_a}")
print(f"Only in B: {only_b}")

# All students
all_students = class_a | class_b
print(f"All students: {all_students}")

Example 5: Configuration Management

# Default settings
defaults = {
    'theme': 'light',
    'language': 'en',
    'notifications': True,
    'auto_save': True
}

# User preferences
user_prefs = {
    'theme': 'dark',
    'notifications': False
}

# Merge settings (user prefs override defaults)
settings = {**defaults, **user_prefs}
print("Final settings:", settings)

Common Patterns

Pattern 1: Group Items by Property

# Group students by grade
students = [
    {'name': 'Alice', 'grade': 'A'},
    {'name': 'Bob', 'grade': 'B'},
    {'name': 'Charlie', 'grade': 'A'},
    {'name': 'Diana', 'grade': 'C'},
    {'name': 'Eve', 'grade': 'B'}
]

by_grade = {}
for student in students:
    grade = student['grade']
    if grade not in by_grade:
        by_grade[grade] = []
    by_grade[grade].append(student['name'])

print(by_grade)
# {'A': ['Alice', 'Charlie'], 'B': ['Bob', 'Eve'], 'C': ['Diana']}

Pattern 2: Count Occurrences

items = ['apple', 'banana', 'apple', 'cherry', 'banana', 'apple']

counts = {}
for item in items:
    counts[item] = counts.get(item, 0) + 1

print(counts)  # {'apple': 3, 'banana': 2, 'cherry': 1}

Pattern 3: Invert Dictionary

# Swap keys and values
original = {'a': 1, 'b': 2, 'c': 3}
inverted = {value: key for key, value in original.items()}
print(inverted)  # {1: 'a', 2: 'b', 3: 'c'}

Practice Exercises

Exercise 1: Phone Book

Create a phone book application with:

  • Add contact
  • Search contact
  • Update contact
  • Delete contact
  • List all contacts

Exercise 2: Inventory System

Build an inventory manager:

  • Add product (name, quantity, price)
  • Update quantity
  • Calculate total inventory value
  • Find low stock items

Exercise 3: Unique Visitor Counter

Track website visitors:

  • Add visitor ID
  • Count unique visitors
  • Find common visitors across days

Sample Solutions

Exercise 1:

phone_book = {}

def add_contact(name, number):
    phone_book[name] = number

def search_contact(name):
    return phone_book.get(name, "Not found")

def update_contact(name, number):
    if name in phone_book:
        phone_book[name] = number
        return True
    return False

def delete_contact(name):
    if name in phone_book:
        del phone_book[name]
        return True
    return False

def list_contacts():
    for name, number in sorted(phone_book.items()):
        print(f"{name}: {number}")

# Usage
add_contact("Alice", "555-0001")
add_contact("Bob", "555-0002")
list_contacts()

Key Takeaways

Dictionaries:

  • Store key-value pairs
  • Fast lookups by key
  • Keys must be immutable
  • Use for mappings and associations

Sets:

  • Store unique values only
  • Fast membership testing
  • Support mathematical operations
  • Use for removing duplicates and set operations

When to Use Which:

  • Dictionary: Store related data (person info, config settings)
  • Set: Track unique items, membership testing, set operations

What's Next?


Dictionaries and sets are powerful tools for organizing data. Master them to write more efficient and Pythonic code!

More places to find me
Mental Health
follow me on Mastodon