PYnative

Python Programming

  • Learn Python
    • Python Tutorials
    • Python Basics
    • Python Interview Q&As
  • Exercises
    • Python Exercises
    • C Programming Exercises
    • C++ Exercises
  • Quizzes
  • Code Editor
    • Online Python Code Editor
    • Online C Compiler
    • Online C++ Compiler
Home » Python Exercises » Python Dictionary Exercises: 40 Coding Problems with Solutions

Python Dictionary Exercises: 40 Coding Problems with Solutions

Updated on: April 19, 2026 | 67 Comments

A Python dictionary is a mutable object that stores data as key-value pairs, with each key separated from its value by a colon (:). Dictionary is the most widely used data structure, and it is necessary to understand its methods and operations.

This article offers 40 Python dictionary practice questions, organized by difficulty, to help you get comfortable with dictionaries through hands-on exercises.

The exercises include dictionary operations like creating, reading, updating, and deleting items. You’ll also practice sorting, merging, filtering with comprehensions, working with nested dictionaries, flattening them.

Each coding challenge includes a Practice Problem, Hint, Solution code, and detailed Explanation, ensuring you don’t just copy code, but genuinely practice and understand how and why it works.

  • All solutions have been fully tested on Python 3.
  • Interactive Learning: Use our Online Code Editor to solve these exercises in real time.

Also Read:

  • Python Dictionary
  • Python Dictionary Quiz: MCQs to help you get familiar with Python dictionary.

Let us know if you have any alternative solutions. It will help other developers.

+ Table of Contents (40 Exercises)

Table of contents

  • Exercise 1: Basic Dictionary Operations
  • Exercise 2: Dictionary Operations
  • Exercise 3: Dictionary from Two Lists
  • Exercise 4: Clear Dictionary
  • Exercise 5: Merge Dictionaries
  • Exercise 6: Access Nested Dictionary
  • Exercise 7: Access ‘history’ Key From a Nested Dictionary
  • Exercise 8: Initialize Dictionary with Default Values
  • Exercise 9: Rename a Key of Dictionary
  • Exercise 10: Delete a List of Keys
  • Exercise 11: Check Value Existence
  • Exercise 12: Sum All Values
  • Exercise 13: Extract Subset of Keys
  • Exercise 14: Map Two Lists (zip)
  • Exercise 15: Count Character Frequencies
  • Exercise 16: Modify Nested Dictionary
  • Exercise 17: Update Deeply Nested Key
  • Exercise 18: Dictionary Comprehension
  • Exercise 19: Filter Dictionary
  • Exercise 20: Key of Minimum Value
  • Exercise 21: Key of Maximum Value
  • Exercise 22: List of Tuples to Dictionary
  • Exercise 23: Find Common Keys
  • Exercise 24: Dictionary Difference
  • Exercise 25: Dictionary Intersection
  • Exercise 26: Word Count
  • Exercise 27: Remove None Values
  • Exercise 28: Sort Dictionary by Keys
  • Exercise 29: Sort Dictionary by Values
  • Exercise 30: Unique Values Check
  • Exercise 31: Check for Subset
  • Exercise 32: Sort Dictionary by Value Length
  • Exercise 33: Key with Longest List
  • Exercise 34: Convert Dictionary to JSON
  • Exercise 35: Invert Dictionary
  • Exercise 36: Invert with Duplicate Values
  • Exercise 37: Flatten Nested Dictionary
  • Exercise 38: Group by First Letter
  • Exercise 39: Merge and Sum Overlapping
  • Exercise 40: Deep vs. Shallow Copy

Exercise 1: Basic Dictionary Operations

Problem Statement: Write a Python program to add a new key-value pair to a dictionary, modify an existing value, and access a specific key.

Purpose: Learn and practice the most fundamental dictionary operations such as insertion, update, and lookup, which form the backbone of working with key-value data in Python.

Given Input: student = {"name": "Alice", "age": 20, "grade": "B"}

Expected Output: {"name": "Alice", "age": 21, "grade": "B", "city": "New York"} and Name: Alice

▼ Hint
  • To add a new key, use dict["new_key"] = value.
  • To modify an existing key, assign a new value to it using the same syntax: dict["existing_key"] = new_value.
  • To access a value, use dict["key"] or the safer dict.get("key") method.
▼ Solution & Explanation

Solution:

student = {"name": "Alice", "age": 20, "grade": "B"}

# Add a new key
student["city"] = "New York"

# Modify an existing key
student["age"] = 21

# Access a key
print(student)
print("Name:", student["name"])Code language: Python (python)

Explanation:

  • student["city"] = "New York": Adds a new key-value pair to the dictionary. If the key does not exist, Python creates it automatically.
  • student["age"] = 21: Overwrites the existing value associated with "age". Dictionary keys are unique, so assigning to an existing key updates it in place.
  • student["name"]: Retrieves the value stored under the key "name". This is the standard bracket-access syntax and raises a KeyError if the key is absent.

Exercise 2: Dictionary Operations

Problem Statement: Write a Python program to remove a specific key from a dictionary, retrieve all key-value pairs, and check whether a given key exists.

Purpose: To builds familiarity with essential dictionary methods pop(), items(), and the in operator, which are routinely used when processing and validating structured data.

Given Input: car = {"brand": "Toyota", "model": "Camry", "year": 2022, "color": "blue"}

Expected Output:

{'brand': 'Toyota', 'model': 'Camry', 'year': 2022}
dict_items([('brand', 'Toyota'), ('model', 'Camry'), ('year', 2022)])
'brand' exists: True
'color' exists: False
▼ Hint
  • Use dict.pop("key") to remove a key and return its value, or del dict["key"] to remove it without returning.
  • Use dict.items() to get all key-value pairs as a view of tuples.
  • Use the in operator — "key" in dict — to check key existence; it returns True or False.
▼ Solution & Explanation

Solution:

car = {"brand": "Toyota", "model": "Camry", "year": 2022, "color": "blue"}

# Remove a key
car.pop("color")
print(car)

# Get all key-value pairs
print(car.items())

# Check key existence
print("'brand' exists:", "brand" in car)
print("'color' exists:", "color" in car)Code language: Python (python)

Explanation:

  • car.pop("color"): Removes the key "color" from the dictionary and returns its value. Unlike del, pop() can accept a default value to avoid a KeyError if the key is missing.
  • car.items(): Returns a dynamic view object of all key-value pairs as tuples. It reflects any subsequent changes to the dictionary.
  • "brand" in car: The in operator checks the dictionary’s keys (not values) and evaluates to True if the key is found, False otherwise.

Exercise 3: Dictionary from Two Lists

Problem Statement: Write a Python program to create a dictionary by mapping two equal-length lists, one containing keys and the other containing values.

Purpose: Learn how to construct a dictionary dynamically from existing data, a common pattern when importing tabular data, pairing labels with values, or building lookup tables.

Given Input: keys = ["name", "age", "city"] and values = ["Bob", 25, "London"]

Expected Output: {'name': 'Bob', 'age': 25, 'city': 'London'}

▼ Hint
  • Use zip(keys, values) to pair elements from both lists by index.
  • Pass the zipped result directly into dict() to create the dictionary in one step.
  • Alternatively, use a dictionary comprehension: {k: v for k, v in zip(keys, values)}.
▼ Solution & Explanation

Solution:

keys = ["name", "age", "city"]
values = ["Bob", 25, "London"]

result = dict(zip(keys, values))
print(result)Code language: Python (python)

Explanation:

  • zip(keys, values): Pairs elements from both lists by their position, producing an iterator of tuples such as ("name", "Bob"), ("age", 25), and so on. It stops at the shorter list if lengths differ.
  • dict(...): Converts the iterator of two-element tuples directly into a dictionary, treating the first element of each tuple as the key and the second as the value.
  • Alternative: A dictionary comprehension {k: v for k, v in zip(keys, values)} achieves the same result and is preferred when you need to transform keys or values during construction.

Exercise 4: Clear Dictionary

Problem Statement: Write a Python program to remove all items from a dictionary while keeping the dictionary object itself intact.

Purpose: Understand the difference between clearing a dictionary and deleting it entirely, an important distinction when the same dictionary reference is shared across multiple parts of a program.

Given Input: inventory = {"apples": 10, "bananas": 5, "oranges": 8}

Expected Output: {}

▼ Hint

Use the built-in dict.clear() method — it empties the dictionary in place without creating a new object or removing the variable.

▼ Solution & Explanation

Solution:

inventory = {"apples": 10, "bananas": 5, "oranges": 8}

inventory.clear()
print(inventory)Code language: Python (python)

Explanation:

  • inventory.clear(): Removes every key-value pair from the dictionary in place. The variable inventory still exists and still points to a dictionary object — it is simply empty.
  • Why not inventory = {}?: Reassigning to {} creates a brand-new dictionary and rebinds the variable, leaving any other references to the original object unaffected. clear() modifies the existing object, so all references see the empty state.

Exercise 5: Merge Dictionaries

Problem Statement: Write a Python program to combine two dictionaries into a single dictionary. If both dictionaries share a key, the value from the second dictionary should take precedence.

Purpose: Merging dictionaries is a frequent task in configuration management, data aggregation, and API response handling, making it essential to know the available approaches and their precedence rules.

Given Input: dict1 = {"a": 1, "b": 2} and dict2 = {"b": 3, "c": 4}

Expected Output: {'a': 1, 'b': 3, 'c': 4}

▼ Hint
  • Use dict1.update(dict2) to merge dict2 into dict1 in place — duplicate keys are overwritten by dict2‘s values.
  • In Python 3.9+, you can use the merge operator: merged = dict1 | dict2 to create a new dictionary without modifying the originals.
  • For older Python versions, use unpacking: merged = {**dict1, **dict2}.
▼ Solution & Explanation

Solution:

dict1 = {"a": 1, "b": 2}
dict2 = {"b": 3, "c": 4}

# Method 1: update() — modifies dict1 in place
dict1.update(dict2)
print(dict1)

# Method 2: unpacking — creates a new dictionary
dict1 = {"a": 1, "b": 2}
merged = {**dict1, **dict2}
print(merged)

# Method 3: merge operator (Python 3.9+)
dict1 = {"a": 1, "b": 2}
merged = dict1 | dict2
print(merged)Code language: Python (python)

Explanation:

  • dict1.update(dict2): Merges all key-value pairs from dict2 into dict1 in place. Where keys overlap, dict2‘s value wins. This method mutates dict1 directly.
  • {**dict1, **dict2}: Unpacks both dictionaries into a new dictionary literal. Keys appearing in both are resolved left to right, so dict2 values take precedence. The originals remain unchanged.
  • dict1 | dict2: The merge operator introduced in Python 3.9 produces a new merged dictionary with the same precedence rules as unpacking, offering a cleaner, more readable syntax.

Exercise 6: Access Nested Dictionary

Problem Statement: Write a Python program to retrieve a specific value from a dictionary that is nested inside another dictionary.

Purpose: Nested dictionaries are widely used to represent structured data such as JSON responses, configuration files, and database records. This exercise trains you to navigate multiple levels of key access.

Given Input: person = {"name": "Carol", "address": {"city": "Paris", "zip": "75001"}}

Expected Output: City: Paris

▼ Hint
  • Chain bracket access to drill into nested levels: dict["outer_key"]["inner_key"].
  • You can also use dict.get("outer_key", {}).get("inner_key") for safer access that avoids a KeyError if any level is missing.
▼ Solution & Explanation

Solution:

person = {"name": "Carol", "address": {"city": "Paris", "zip": "75001"}}

city = person["address"]["city"]
print("City:", city)Code language: Python (python)

Explanation:

  • person["address"]: Accesses the value stored under "address", which is itself a dictionary: {"city": "Paris", "zip": "75001"}.
  • person["address"]["city"]: Chains a second bracket access on the inner dictionary to retrieve "Paris". Each pair of brackets descends one level deeper into the nested structure.
  • Safer alternative: person.get("address", {}).get("city") returns None instead of raising a KeyError if either "address" or "city" is absent, making it preferable for untrusted or incomplete data.

Exercise 7: Access ‘history’ Key From a Nested Dictionary

Problem Statement: Write a Python program to access the value associated with the key 'history' from a dictionary nested within a larger data structure.

Purpose: Understand multi-level dictionary traversal using a realistic data structure that resembles student records, course databases, or API payloads situations where a specific field must be extracted from deeply nested data.

Given Input: student = {"name": "Dave", "grades": {"math": 88, "science": 92, "history": 75}}

Expected Output: History grade: 75

▼ Hint
  • First access the "grades" key to get the inner dictionary, then access "history" within it.
  • You can do this in one expression: student["grades"]["history"].
▼ Solution & Explanation

Solution:

student = {"name": "Dave", "grades": {"math": 88, "science": 92, "history": 75}}

history_grade = student["grades"]["history"]
print("History grade:", history_grade)Code language: Python (python)

Explanation:

  • student["grades"]: Retrieves the nested dictionary {"math": 88, "science": 92, "history": 75} stored under the "grades" key.
  • student["grades"]["history"]: Applies a second key lookup on the inner dictionary to extract the integer value 75. This chained syntax is the standard way to navigate nested dictionaries in Python.
  • Practical note: In real applications such as JSON API responses or configuration files, nesting can go three or more levels deep. For such cases, consider using .get() at each level or a helper function to handle missing keys gracefully.

Exercise 8: Initialize Dictionary with Default Values

Problem Statement: Write a Python program to create a dictionary from a list of keys, assigning the same default value to every key.

Purpose: Initializing dictionaries with default values is a common setup step in counting, scoring, and configuration tasks, it ensures every expected key exists before any data is processed.

Given Input: keys = ["math", "science", "english", "history"] and default = 0

Expected Output: {'math': 0, 'science': 0, 'english': 0, 'history': 0}

▼ Hint
  • Use the class method dict.fromkeys(keys, default) — it creates a new dictionary from an iterable of keys, assigning the same default value to each one.
  • Alternatively, use a dictionary comprehension: {k: default for k in keys}.
  • Avoid using a mutable default (like a list) with fromkeys() — all keys would share the same object reference.
▼ Solution & Explanation

Solution:

keys = ["math", "science", "english", "history"]
default = 0

scores = dict.fromkeys(keys, default)
print(scores)Code language: Python (python)

Explanation:

  • dict.fromkeys(keys, default): A class method that accepts an iterable of keys and an optional default value, returning a new dictionary where every key maps to that same value. If the second argument is omitted, all keys default to None.
  • {k: default for k in keys}: A dictionary comprehension that achieves the same result. It is preferable when the default value needs to be computed or transformed per key rather than shared directly.
  • Mutable default warning: Using dict.fromkeys(keys, []) assigns the same list object to every key. Modifying one key’s list modifies all of them. Use a comprehension — {k: [] for k in keys} — to give each key its own independent list.

Exercise 9: Rename a Key of Dictionary

Problem Statement: Write a Python program to rename an existing key in a dictionary while preserving its associated value and the rest of the dictionary unchanged.

Purpose: Renaming keys comes up frequently when normalizing data from external sources — such as API responses or CSV headers, to match the field names expected by your application.

Given Input: employee = {"fname": "John", "age": 30, "dept": "Engineering"} — rename "fname" to "first_name"

Expected Output: {'first_name': 'John', 'age': 30, 'dept': 'Engineering'}

▼ Hint
  • Dictionaries have no built-in rename method — combine two operations: assign the old key’s value to the new key, then delete the old key.
  • Use dict.pop("old_key") to remove the old key and retrieve its value in one step, then assign it to dict["new_key"].
▼ Solution & Explanation

Solution:

employee = {"fname": "John", "age": 30, "dept": "Engineering"}

employee["first_name"] = employee.pop("fname")
print(employee)Code language: Python (python)

Explanation:

  • employee.pop("fname"): Removes the key "fname" from the dictionary and returns its value "John" in a single atomic operation, avoiding the need for a temporary variable.
  • employee["first_name"] = ...: Assigns the returned value to the new key "first_name", effectively completing the rename. The rest of the dictionary is untouched.
  • Insertion order note: In Python 3.7+, dictionaries preserve insertion order. The renamed key will appear at the end of the dictionary rather than in the original position of "fname". If order matters, rebuild the dictionary with a comprehension that substitutes the key inline.

Exercise 10: Delete a List of Keys

Problem Statement: Write a Python program to remove multiple specific keys from a dictionary in one operation.

Purpose: Bulk key removal is useful when filtering out sensitive fields before logging, stripping unwanted metadata from API responses, or trimming a record down to only the fields your application needs.

Given Input: product = {"id": 101, "name": "Laptop", "price": 999, "stock": 50, "warehouse": "A3"} — remove keys ["stock", "warehouse"]

Expected Output: {'id': 101, 'name': 'Laptop', 'price': 999}

▼ Hint
  • Loop over the list of keys to remove and call del dict[key] or dict.pop(key, None) for each one.
  • Using pop(key, None) is safer than del because it will not raise a KeyError if a key in the removal list does not exist in the dictionary.
  • Alternatively, use a dictionary comprehension to build a new dictionary that excludes the unwanted keys: {k: v for k, v in dict.items() if k not in keys_to_remove}.
▼ Solution & Explanation

Solution:

product = {"id": 101, "name": "Laptop", "price": 999, "stock": 50, "warehouse": "A3"}
keys_to_remove = ["stock", "warehouse"]

for key in keys_to_remove:
    product.pop(key, None)

print(product)Code language: Python (python)

Explanation:

  • for key in keys_to_remove: Iterates over each key that should be deleted, allowing the same removal logic to be applied to any number of keys without repeating code.
  • product.pop(key, None): Removes the key if it exists and silently returns None if it does not, preventing a KeyError crash when a key in the removal list is absent from the dictionary.
  • Comprehension alternative: {k: v for k, v in product.items() if k not in keys_to_remove} produces a new filtered dictionary without mutating the original — preferable when you need to keep the original intact alongside the trimmed version.

Exercise 11: Check Value Existence

Problem Statement: Write a Python program to verify whether a specific value is present anywhere in a dictionary.

Purpose: Checking for value existence is common in validation workflows — for example, confirming that a username, status code, or category is already recorded before inserting a duplicate entry.

Given Input: roles = {"alice": "admin", "bob": "editor", "carol": "viewer"} — check if "editor" and "manager" are present

Expected Output:

'editor' exists as a value: True
'manager' exists as a value: False
▼ Hint
  • The in operator checks keys by default — to search values, use it against dict.values(): "editor" in dict.values().
  • dict.values() returns a view object; the in operator performs a linear scan through it, so this is an O(n) operation.
▼ Solution & Explanation

Solution:

roles = {"alice": "admin", "bob": "editor", "carol": "viewer"}

print("'editor' exists as a value:", "editor" in roles.values())
print("'manager' exists as a value:", "manager" in roles.values())Code language: Python (python)

Explanation:

  • roles.values(): Returns a dynamic view object containing all the values in the dictionary — in this case dict_values(['admin', 'editor', 'viewer']). The view reflects any subsequent changes to the dictionary.
  • "editor" in roles.values(): The in operator performs a sequential scan through the values view and returns True as soon as a match is found, or False if the entire view is exhausted without a match.
  • Key vs value search: "alice" in roles checks keys and runs in O(1) time thanks to hashing. "alice" in roles.values() checks values and runs in O(n) time. For frequent value lookups on large dictionaries, consider maintaining an inverse mapping.

Exercise 12: Sum All Values

Problem Statement: Write a Python program to calculate the total of all numerical values stored in a dictionary.

Purpose: Summing dictionary values is a fundamental aggregation operation used in budgeting, scorekeeping, inventory totals, and any scenario where a collection of labelled numeric measurements must be combined into a single figure.

Given Input: expenses = {"rent": 1200, "food": 300, "transport": 150, "utilities": 200}

Expected Output: Total expenses: 1850

▼ Hint
  • Pass dict.values() directly into Python’s built-in sum() function.
  • Alternatively, use a for loop with a running total variable to accumulate the values manually — this approach mirrors the logic covered in Exercise 1.
▼ Solution & Explanation

Solution:

expenses = {"rent": 1200, "food": 300, "transport": 150, "utilities": 200}

total = sum(expenses.values())
print("Total expenses:", total)Code language: Python (python)

Explanation:

  • expenses.values(): Returns a view of all the dictionary’s values — dict_values([1200, 300, 150, 200]) — without needing to extract them into a separate list first.
  • sum(...): Python’s built-in sum() accepts any iterable of numbers, including a values view, and returns their cumulative total. It is the most concise and readable approach for this task.
  • Loop alternative: A manual loop — total = 0; for v in expenses.values(): total += v — produces the same result and is useful when you need to apply a condition or transformation to each value before adding it to the running total.

Exercise 13: Extract Subset of Keys

Problem Statement: Write a Python program to create a new dictionary containing only a specified subset of keys from an existing dictionary.

Purpose: Extracting a key subset is essential when preparing data for display, serialisation, or an API call, you often need to expose only certain fields from a larger record while keeping the original intact.

Given Input: user = {"id": 42, "username": "jdoe", "email": "jdoe@example.com", "password": "s3cr3t", "joined": "2021-03-15"} — extract only ["id", "username", "email"]

Expected Output: {'id': 42, 'username': 'jdoe', 'email': 'jdoe@example.com'}

▼ Hint
  • Use a dictionary comprehension that iterates over the desired keys and looks each one up in the original dictionary: {k: dict[k] for k in keys_to_keep}.
  • If some keys in the subset might be absent from the original, use dict.get(k) inside the comprehension to avoid a KeyError.
▼ Solution & Explanation

Solution:

user = {"id": 42, "username": "jdoe", "email": "jdoe@example.com", "password": "s3cr3t", "joined": "2021-03-15"}
keys_to_keep = ["id", "username", "email"]

subset = {k: user[k] for k in keys_to_keep}
print(subset)Code language: Python (python)

Explanation:

  • {k: user[k] for k in keys_to_keep}: A dictionary comprehension that iterates over keys_to_keep and retrieves each corresponding value from user. Only the specified keys appear in the resulting dictionary; all others are silently excluded.
  • Original preserved: Because a new dictionary is constructed rather than modifying user in place, the original record — including sensitive fields like "password" — remains fully intact for use elsewhere in the program.
  • Safe variant: Replace user[k] with user.get(k) to handle cases where a requested key may not exist in the source dictionary, returning None for missing keys rather than raising a KeyError.

Exercise 14: Map Two Lists (zip)

Problem Statement: Write a Python program that uses zip() to combine a list of keys and a list of values into a single dictionary.

Purpose: Mapping two parallel lists into a dictionary with zip() is a pattern that appears constantly when processing tabular data, for example, pairing a header row with a data row read from a CSV file to produce a named-field record.

Given Input: attributes = ["brand", "model", "year", "color"] and details = ["Honda", "Civic", 2023, "silver"]

Expected Output: {'brand': 'Honda', 'model': 'Civic', 'year': 2023, 'color': 'silver'}

▼ Hint
  • zip(attributes, details) produces an iterator of (key, value) tuples paired by index.
  • Wrap it in dict() for a one-liner, or use a dictionary comprehension if you need to transform the keys or values during construction.
  • If the two lists differ in length, zip() stops at the shorter one — use itertools.zip_longest() if you need to handle unequal lengths explicitly.
▼ Solution & Explanation

Solution:

attributes = ["brand", "model", "year", "color"]
details = ["Honda", "Civic", 2023, "silver"]

car = dict(zip(attributes, details))
print(car)Code language: Python (python)

Explanation:

  • zip(attributes, details): Lazily pairs elements from both lists by index, yielding tuples such as ("brand", "Honda") and ("year", 2023) one at a time. No intermediate list is created, making it memory-efficient for large inputs.
  • dict(...): Consumes the zip iterator and constructs a dictionary by treating the first element of each tuple as the key and the second as the value — identical in result to Exercise 3, but applied here to a vehicle-attributes context to reinforce the pattern.
  • CSV row example: When reading a CSV file, headers and row are both lists of strings. dict(zip(headers, row)) instantly converts a raw data row into a named-field dictionary — the same pattern used internally by Python’s csv.DictReader.

Exercise 15: Count Character Frequencies

Problem Statement: Write a Python program to count how many times each character appears in a given string, storing the results in a dictionary.

Purpose: Character frequency counting is a foundational technique used in text analysis, data compression algorithms, cryptography, and natural language processing, making it an essential pattern to master early.

Given Input: text = "hello world"

Expected Output: {'h': 1, 'e': 1, 'l': 3, 'o': 2, ' ': 1, 'w': 1, 'r': 1, 'd': 1}

▼ Hint
  • Loop over each character in the string and use dict.get(char, 0) to retrieve the current count (defaulting to 0 if the character has not been seen yet), then increment it by 1.
  • Alternatively, use collections.Counter(text) for a one-liner that returns a dictionary-like object of character counts.
  • You can also use dict.setdefault(char, 0) before incrementing — it inserts the key with a default value only if it does not already exist.
▼ Solution & Explanation

Solution:

text = "hello world"

freq = {}
for char in text:
    freq[char] = freq.get(char, 0) + 1

print(freq)Code language: Python (python)

Explanation:

  • for char in text: Iterates over the string one character at a time, including spaces. Every character in the string — not just letters — is counted, so whitespace and punctuation are included unless explicitly filtered out.
  • freq.get(char, 0) + 1: Retrieves the current count for char, falling back to 0 if the key does not yet exist, then adds 1. The result is written back, either creating the key on its first occurrence or incrementing an existing count.
  • collections.Counter(text): A standard-library shortcut that produces the same frequency mapping in a single call. Counter is a subclass of dict, so it supports all the same operations plus extras like most_common(n) — preferable when further analysis of the counts is needed.

Exercise 16: Modify Nested Dictionary

Problem Statement: Write a Python program to change a specific value inside a dictionary that is nested within another dictionary.

Purpose: Modifying nested dictionary values is a routine task when updating records in hierarchical data structures such as configuration objects, user profiles, or JSON documents loaded from an API.

Given Input: company = {"name": "TechCorp", "location": {"city": "Berlin", "country": "Germany"}} — change the city to "Munich"

Expected Output: {'name': 'TechCorp', 'location': {'city': 'Munich', 'country': 'Germany'}}

▼ Hint
  • Chain bracket access to navigate to the target level, then assign the new value directly: dict["outer"]["inner"] = new_value.
  • There is no need to rebuild the outer dictionary — assigning to a nested key modifies the inner dictionary object in place.
▼ Solution & Explanation

Solution:

company = {"name": "TechCorp", "location": {"city": "Berlin", "country": "Germany"}}

company["location"]["city"] = "Munich"
print(company)Code language: Python (python)

Explanation:

  • company["location"]: Retrieves a reference to the inner dictionary object {"city": "Berlin", "country": "Germany"}. Because dictionaries are mutable, this is a live reference — not a copy — so any assignment through it modifies the original nested structure directly.
  • company["location"]["city"] = "Munich": Navigates to the inner dictionary via the reference obtained above and overwrites the value of "city". The outer dictionary and the "country" key are both left untouched.
  • In-place vs rebuild: This approach mutates the existing structure. If you need an updated copy while preserving the original, use copy.deepcopy(company) first, then modify the copy — a shallow copy would still share the inner dictionary object and lead to unexpected side effects.

Exercise 17: Update Deeply Nested Key

Problem Statement: Write a Python program to update a value located multiple levels deep inside a nested dictionary structure.

Purpose: Real-world data such as configuration files, JSON API payloads, or document-store records is often nested three or more levels deep. This exercise trains you to navigate and update such structures confidently without disturbing surrounding data.

Given Input: data = {"school": {"department": {"class": {"teacher": "Mr. Smith", "students": 30}}}} — update students to 35

Expected Output: {'school': {'department': {'class': {'teacher': 'Mr. Smith', 'students': 35}}}}

▼ Hint
  • Continue chaining bracket access for each additional level: dict["level1"]["level2"]["level3"] = new_value.
  • Each intermediate key returns the next nested dictionary, so you can keep chaining as many levels as needed before the final assignment.
▼ Solution & Explanation

Solution:

data = {"school": {"department": {"class": {"teacher": "Mr. Smith", "students": 30}}}}

data["school"]["department"]["class"]["students"] = 35
print(data)Code language: Python (python)

Explanation:

  • data["school"]["department"]["class"]: Traverses three levels of nesting, each bracket lookup returning the next inner dictionary as a live mutable reference. No intermediate variables are needed because each result is immediately used to access the next level.
  • ["students"] = 35: Performs the final assignment at the innermost dictionary, updating students from 30 to 35. All parent dictionaries remain unchanged because only the target key’s value is overwritten.
  • Error handling tip: If any intermediate key might be absent, chaining raw bracket access raises a KeyError. For defensive traversal, use a helper that calls .get() at each level and returns a fallback, or use a library like glom which is designed specifically for safe deep access and update in nested structures.

Exercise 18: Dictionary Comprehension

Problem Statement: Write a Python program to generate a dictionary of the squares of numbers from 1 to 10 using a dictionary comprehension in a single line.

Purpose: Dictionary comprehensions offer a concise, readable alternative to building dictionaries with loops. Mastering this syntax is valuable for data transformation tasks where keys and values are derived from a common iterable.

Given Input: Numbers 1 through 10 (generated with range())

Expected Output: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81, 10: 100}

▼ Hint
  • The syntax for a dictionary comprehension is {key_expr: value_expr for var in iterable}.
  • Use range(1, 11) as the iterable, n as the key expression, and n ** 2 as the value expression.
  • You can also add an optional if condition at the end to filter which items are included — useful for generating squares of only even or odd numbers.
▼ Solution & Explanation

Solution:

squares = {n: n ** 2 for n in range(1, 11)}
print(squares)Code language: Python (python)

Explanation:

  • {n: n ** 2 for n in range(1, 11)}: A dictionary comprehension that iterates over integers 1 through 10, using each integer n as the key and its square n ** 2 as the corresponding value. The entire structure is built and returned as a single expression.
  • n ** 2: The exponentiation operator raises n to the power of 2. It is equivalent to n * n but is more readable and idiomatic for powers in Python.
  • Adding a filter: Appending an if clause — {n: n ** 2 for n in range(1, 11) if n % 2 == 0} — restricts the comprehension to even numbers only, demonstrating how comprehensions can combine generation and filtering in one concise expression.

Exercise 19: Filter Dictionary

Problem Statement: Write a Python program to create a new dictionary containing only the key-value pairs from an existing dictionary where the value meets a specified condition.

Purpose: Filtering dictionaries by value is a common data-cleaning and reporting operation. for example, keeping only high-scoring entries, retaining active records, or isolating items above a threshold before further processing.

Given Input: scores = {"Alice": 82, "Bob": 45, "Carol": 91, "Dave": 58, "Eve": 73} — keep only scores greater than 60

Expected Output: {'Alice': 82, 'Carol': 91, 'Eve': 73}

▼ Hint
  • Use a dictionary comprehension with an if condition: {k: v for k, v in dict.items() if v > 60}.
  • Iterate over dict.items() to get both the key and value in each iteration so you can test the value while keeping the key in the result.
▼ Solution & Explanation

Solution:

scores = {"Alice": 82, "Bob": 45, "Carol": 91, "Dave": 58, "Eve": 73}

passing = {k: v for k, v in scores.items() if v > 60}
print(passing)Code language: Python (python)

Explanation:

  • scores.items(): Returns a view of all key-value pairs as tuples, enabling the comprehension to unpack each pair into k (the name) and v (the score) simultaneously on every iteration.
  • if v > 60: Acts as a guard clause inside the comprehension — only pairs where the value exceeds 60 are included in the resulting dictionary. Pairs that fail the condition are silently skipped.
  • Original preserved: The comprehension builds a brand-new dictionary, leaving scores completely unchanged. This non-destructive pattern is preferred over deleting keys from the original when both the full and filtered versions may be needed later.

Exercise 20: Key of Minimum Value

Problem Statement: Write a Python program to find the key associated with the smallest numerical value in a dictionary.

Purpose: Locating the key of a minimum value is essential in ranking and optimisation tasks such as identifying the lowest-priced item, the least-visited page, or the team member with the fewest assigned tasks.

Given Input: stock = {"apples": 34, "bananas": 12, "oranges": 57, "grapes": 8, "mangoes": 23}

Expected Output: Lowest stock item: grapes

▼ Hint
  • Use min(dict, key=dict.get) — this passes each key through dict.get to retrieve its value for comparison, returning the key whose value is the smallest.
  • Alternatively, use min(dict.items(), key=lambda item: item[1]) to get the full (key, value) tuple for the minimum entry.
▼ Solution & Explanation

Solution:

stock = {"apples": 34, "bananas": 12, "oranges": 57, "grapes": 8, "mangoes": 23}

lowest = min(stock, key=stock.get)
print("Lowest stock item:", lowest)Code language: Python (python)

Explanation:

  • min(stock, ...): When a dictionary is passed to min() without a key argument it iterates over the keys. The key parameter tells min() what value to use for comparison instead of the raw iteration item.
  • key=stock.get: Passes the bound method stock.get as the comparison function. For each key, min() calls stock.get(key) to obtain its numeric value and uses that for the minimum comparison — returning the key itself, not the value.
  • Getting both key and value: min(stock.items(), key=lambda item: item[1]) returns the full tuple ('grapes', 8), which is convenient when you need both the name and the count in the same expression.

Exercise 21: Key of Maximum Value

Problem Statement: Write a Python program to find the key associated with the highest numerical value in a dictionary.

Purpose: Finding the top-performing key is one of the most common dictionary queries used for leaderboards, determining the best-selling product, identifying the highest-scoring student, or finding the most frequent word in a text analysis.

Given Input: scores = {"Alice": 88, "Bob": 95, "Carol": 72, "Dave": 95, "Eve": 84}

Expected Output: Top scorer: Bob

▼ Hint
  • Use max(dict, key=dict.get) — the same pattern as Exercise 20 but with max() instead of min().
  • When multiple keys share the maximum value, max() returns the first one encountered in iteration order. To retrieve all tied keys, use a list comprehension: [k for k, v in dict.items() if v == max(dict.values())].
▼ Solution & Explanation

Solution:

scores = {"Alice": 88, "Bob": 95, "Carol": 72, "Dave": 95, "Eve": 84}

top = max(scores, key=scores.get)
print("Top scorer:", top)

# Bonus: retrieve all keys that share the maximum score
best_score = max(scores.values())
all_top = [k for k, v in scores.items() if v == best_score]
print("All top scorers:", all_top)Code language: Python (python)

Explanation:

  • max(scores, key=scores.get): Mirrors the min() pattern from Exercise 20 — iterates over the dictionary’s keys and uses scores.get to retrieve each key’s value for comparison, returning the key whose value is the largest. When a tie exists, the first key encountered in insertion order is returned.
  • max(scores.values()): Computes the highest score as a standalone number. Storing it in best_score avoids recalculating the maximum on every iteration of the list comprehension, keeping the tie-finding logic efficient.
  • [k for k, v in scores.items() if v == best_score]: Collects every key whose value matches the maximum, handling ties correctly. In this example both "Bob" and "Dave" scored 95, so the bonus output is ['Bob', 'Dave'] — a result that max() alone cannot provide.

Exercise 22: List of Tuples to Dictionary

Problem Statement: Write a Python program to convert a list of key-value tuples into a dictionary without using any loops.

Purpose: This exercise helps you practice using Python’s built-in dict() constructor to transform structured data directly into a dictionary, a common pattern in data wrangling and API response parsing.

Given Input: pairs = [("name", "Alice"), ("age", 25), ("city", "Paris")]

Expected Output: {'name': 'Alice', 'age': 25, 'city': 'Paris'}

▼ Hint

Pass the list of tuples directly to the built-in dict() constructor.

▼ Solution & Explanation

Solution:

pairs = [("name", "Alice"), ("age", 25), ("city", "Paris")]

result = dict(pairs)

print(result)Code language: Python (python)

Explanation:

  • dict(pairs): The built-in dict() constructor accepts an iterable of two-item iterables (such as tuples) and maps the first element of each tuple to a key and the second to its value.
  • No loop needed: Because dict() handles the iteration internally, you get a clean one-liner without writing an explicit for loop.
  • Duplicate keys: If two tuples share the same first element, the last one wins, as dictionary keys must be unique.

Exercise 23: Find Common Keys

Problem Statement: Write a Python program to identify all keys that are present in both of two given dictionaries.

Purpose: This exercise builds your understanding of dictionary views and set operations, which are widely used when comparing datasets, merging configurations, or validating overlapping fields.

Given Input: d1 = {"a": 1, "b": 2, "c": 3} and d2 = {"b": 20, "c": 30, "d": 40}

Expected Output: Common keys: {'b', 'c'}

▼ Hint
  • Dictionary .keys() returns a view object that supports set operations.
  • Use the & operator between two .keys() views to get their intersection.
▼ Solution & Explanation

Solution:

d1 = {"a": 1, "b": 2, "c": 3}
d2 = {"b": 20, "c": 30, "d": 40}

common_keys = d1.keys() & d2.keys()

print("Common keys:", common_keys)Code language: Python (python)

Explanation:

  • d1.keys(): Returns a dict_keys view, which behaves like a set and supports operations such as union, intersection, and difference.
  • & operator: Applies set intersection to the two key views, producing only the keys found in both dictionaries.
  • Order not guaranteed: The result is a set, so the displayed order of keys may vary between runs.

Exercise 24: Dictionary Difference

Problem Statement: Write a Python program to find all keys that exist in the first dictionary but are absent from the second dictionary.

Purpose: This exercise trains you to use set difference on dictionary views, a practical skill for detecting missing fields when comparing records, configuration files, or API payloads.

Given Input: d1 = {"a": 1, "b": 2, "c": 3} and d2 = {"b": 20, "d": 40}

Expected Output: Keys only in d1: {'a', 'c'}

▼ Hint
  • Use the - operator between two .keys() views to subtract one set of keys from another.
  • The expression d1.keys() - d2.keys() returns keys present in d1 but not in d2.
▼ Solution & Explanation

Solution:

d1 = {"a": 1, "b": 2, "c": 3}
d2 = {"b": 20, "d": 40}

only_in_d1 = d1.keys() - d2.keys()

print("Keys only in d1:", only_in_d1)Code language: Python (python)

Explanation:

  • d1.keys() - d2.keys(): Applies set difference, returning a new set of keys that appear in d1 but not in d2.
  • Asymmetric operation: The order of operands matters. d1.keys() - d2.keys() and d2.keys() - d1.keys() produce different results.
  • Alternative: You can also write d1.keys().difference(d2.keys()) for the same effect using the explicit method form.

Exercise 25: Dictionary Intersection

Problem Statement: Write a Python program to create a new dictionary containing only the key-value pairs that are identical in both input dictionaries.

Purpose: This exercise deepens your understanding of dictionary views and dictionary comprehensions, useful when reconciling two data sources and keeping only the entries they fully agree on.

Given Input: d1 = {"a": 1, "b": 2, "c": 3} and d2 = {"a": 1, "b": 99, "c": 3}

Expected Output: Intersection: {'a': 1, 'c': 3}

▼ Hint
  • Use d1.keys() & d2.keys() to get the common keys first.
  • Then use a dictionary comprehension to keep only the pairs where d1[k] == d2[k].
▼ Solution & Explanation

Solution:

d1 = {"a": 1, "b": 2, "c": 3}
d2 = {"a": 1, "b": 99, "c": 3}

intersection = {k: d1[k] for k in d1.keys() & d2.keys() if d1[k] == d2[k]}

print("Intersection:", intersection)Code language: Python (python)

Explanation:

  • d1.keys() & d2.keys(): Produces the set of keys shared by both dictionaries, so the comprehension only examines relevant keys.
  • if d1[k] == d2[k]: The filter condition ensures that only pairs where both dictionaries hold the exact same value are included in the result.
  • Dictionary comprehension: The {k: d1[k] for k in ...} syntax builds the new dictionary in a single readable expression without an explicit loop.

Exercise 26: Word Count

Problem Statement: Write a Python program to count the frequency of each word in a string, treating words case-insensitively so that “The” and “the” are counted as the same word.

Purpose: This exercise practises string normalization, splitting, and dictionary-based frequency counting, skills that form the foundation of text analysis, search indexing, and natural language processing tasks.

Given Input: text = "the cat sat on the mat the cat"

Expected Output: {'the': 3, 'cat': 2, 'sat': 1, 'on': 1, 'mat': 1}

▼ Hint
  • Call .lower() on the string before splitting so all words are normalized to lowercase.
  • Use .split() to break the string into a list of words.
  • Use dict.get(word, 0) + 1 inside a loop, or consider collections.Counter for a concise alternative.
▼ Solution & Explanation

Solution:

text = "the cat sat on the mat the cat"

word_count = {}
for word in text.lower().split():
    word_count[word] = word_count.get(word, 0) + 1

print(word_count)Code language: Python (python)

Explanation:

  • text.lower(): Converts the entire string to lowercase before processing, ensuring “The” and “the” are treated as the same token.
  • .split(): Splits on any whitespace and discards extra spaces, producing a clean list of words.
  • word_count.get(word, 0) + 1: Retrieves the current count for a word, defaulting to 0 if the word has not been seen yet, then increments it by one.
  • Alternative: from collections import Counter; word_count = Counter(text.lower().split()) achieves the same result in a single line.

Exercise 27: Remove None Values

Problem Statement: Write a Python program to remove all key-value pairs from a dictionary where the value is None.

Purpose: This exercise practises filtering dictionaries with a comprehension, a pattern that appears frequently when cleaning up API responses, database records, or configuration objects that may contain missing fields.

Given Input: data = {"name": "Alice", "age": None, "city": "Paris", "score": None}

Expected Output: {'name': 'Alice', 'city': 'Paris'}

▼ Hint
  • Use a dictionary comprehension with a condition to include only pairs where the value is not None.
  • The condition should use is not None rather than != None for correct identity checking.
▼ Solution & Explanation

Solution:

data = {"name": "Alice", "age": None, "city": "Paris", "score": None}

cleaned = {k: v for k, v in data.items() if v is not None}

print(cleaned)Code language: Python (python)

Explanation:

  • data.items(): Returns each key-value pair as a tuple, allowing the comprehension to unpack both k and v in a single expression.
  • if v is not None: Uses identity comparison rather than equality, which is the recommended way to test for None in Python and avoids unexpected behaviour with objects that override __eq__.
  • Non-destructive: The comprehension produces a new dictionary called cleaned, leaving the original data unchanged. If you need in-place removal, you can reassign: data = cleaned.

Exercise 28: Sort Dictionary by Keys

Problem Statement: Write a Python program to sort a dictionary by its keys and return the result as a new dictionary with items in ascending key order.

Purpose: This exercise practises combining sorted() with dictionary construction, a technique useful when producing consistent output for logging, serialization, or display purposes.

Given Input: data = {"banana": 3, "apple": 5, "cherry": 1, "date": 4}

Expected Output: {'apple': 5, 'banana': 3, 'cherry': 1, 'date': 4}

▼ Hint
  • Pass data.items() to sorted(), which sorts tuples by their first element (the key) by default.
  • Wrap the result in dict() to convert the sorted list of tuples back into a dictionary.
▼ Solution & Explanation

Solution:

data = {"banana": 3, "apple": 5, "cherry": 1, "date": 4}

sorted_data = dict(sorted(data.items()))

print(sorted_data)Code language: Python (python)

Explanation:

  • data.items(): Produces a view of (key, value) tuples that can be passed directly to sorted().
  • sorted(...): Sorts the tuples in ascending order by their first element (the key) using Python’s default lexicographic comparison for strings.
  • dict(...): Converts the sorted list of tuples back into a dictionary. Since Python 3.7, dictionaries maintain insertion order, so the result preserves the sorted sequence.
  • Descending order: To sort in reverse, pass reverse=True to sorted(): dict(sorted(data.items(), reverse=True)).

Exercise 29: Sort Dictionary by Values

Problem Statement: Write a Python program to sort a dictionary’s items based on their values in ascending order.

Purpose: This exercise helps you practice working with dictionary methods, using the sorted() function with a custom key, and reconstructing a dictionary from sorted pairs – skills useful in ranking, leaderboards, and data ordering tasks.

Given Input: scores = {"Alice": 88, "Bob": 72, "Charlie": 95, "Diana": 60}

Expected Output:

{"Diana": 60, "Bob": 72, "Alice": 88, "Charlie": 95}
▼ Hint
  • Use dict.items() to get key-value pairs as tuples.
  • Pass those pairs to sorted() with key=lambda item: item[1] to sort by value.
  • Wrap the result in dict() to convert the sorted list of tuples back into a dictionary.
▼ Solution & Explanation

Solution:

scores = {"Alice": 88, "Bob": 72, "Charlie": 95, "Diana": 60}

sorted_scores = dict(sorted(scores.items(), key=lambda item: item[1]))

print(sorted_scores)Code language: Python (python)

Explanation:

  • scores.items(): Returns all key-value pairs as a view of tuples, e.g., [("Alice", 88), ...].
  • key=lambda item: item[1]: Tells sorted() to compare items by their second element (the value), not the key.
  • dict(...): Converts the sorted list of tuples back into a regular dictionary. Python 3.7+ preserves insertion order, so the result stays sorted.
  • Alternative: To sort in descending order, add reverse=True inside sorted().

Exercise 30: Unique Values Check

Problem Statement: Write a Python program to check whether all values in a dictionary are distinct (i.e., no two keys share the same value).

Purpose: This exercise helps you practice extracting dictionary values, understanding set properties, and comparing lengths to detect duplicates – a common pattern in data validation and integrity checks.

Given Input: data = {"a": 1, "b": 2, "c": 3, "d": 2}

Expected Output: False

▼ Hint
  • Use dict.values() to extract all values.
  • Convert the values to a set – sets automatically remove duplicates.
  • If the length of the set equals the length of the original values list, all values are unique.
▼ Solution & Explanation

Solution:

data = {"a": 1, "b": 2, "c": 3, "d": 2}

values = list(data.values())
is_unique = len(values) == len(set(values))

print(is_unique)Code language: Python (python)

Explanation:

  • data.values(): Returns a view of all values in the dictionary, here [1, 2, 3, 2].
  • set(values): Creates a set from the values, eliminating any duplicates. Here it becomes {1, 2, 3}.
  • len(values) == len(set(values)): If both lengths are equal, no duplicates exist. Since 4 does not equal 3, the result is False.
  • Alternative: You can write this as a one-liner: is_unique = len(data) == len(set(data.values())).

Exercise 31: Check for Subset

Problem Statement: Write a Python program to verify whether one dictionary is a subset of another, meaning all key-value pairs of the smaller dictionary exist in the larger one.

Purpose: This exercise helps you practice dictionary comparison, use of the .items() method, and set operations – techniques commonly used in configuration matching, permission checks, and data filtering.

Given Input: main = {"a": 1, "b": 2, "c": 3, "d": 4} and subset = {"a": 1, "c": 3}

Expected Output: True

▼ Hint
  • Convert both dictionaries’ items to sets using .items().
  • Use the <= operator on sets to check if one is a subset of the other.
  • Alternatively, use the .issubset() method on the set of the smaller dictionary’s items.
▼ Solution & Explanation

Solution:

main = {"a": 1, "b": 2, "c": 3, "d": 4}
subset = {"a": 1, "c": 3}
is_subset = subset.items() <= main.items()
print(is_subset)Code language: Python (python)

Explanation:

  • subset.items(): Returns a view of the key-value pairs of the smaller dictionary as a set-like object: {("a", 1), ("c", 3)}.
  • main.items(): Returns a similar view for the larger dictionary. Dictionary item views support set operations directly.
  • <= operator: When used on dict item views, it checks whether every pair in subset.items() also exists in main.items(), returning True or False.
  • Alternative: subset.items().issubset(main.items()) produces the same result and may read more clearly in some codebases.

Exercise 32: Sort Dictionary by Value Length

Problem Statement: Write a Python program to sort a dictionary’s items by the length of their string values, from shortest to longest.

Purpose: This exercise helps you practice combining sorted() with a custom key function, working with string properties inside dictionaries, and rebuilding ordered dictionaries – useful in text processing and display formatting tasks.

Given Input: words = {"a": "banana", "b": "kiwi", "c": "strawberry", "d": "fig"}

Expected Output:

{"d": "fig", "b": "kiwi", "a": "banana", "c": "strawberry"}
▼ Hint
  • Use dict.items() to get key-value pairs.
  • Pass a lambda to the key parameter of sorted() that returns len(item[1]) – the length of the value string.
  • Wrap the result in dict() to get the final sorted dictionary.
▼ Solution & Explanation

Solution:

words = {"a": "banana", "b": "kiwi", "c": "strawberry", "d": "fig"}

sorted_words = dict(sorted(words.items(), key=lambda item: len(item[1])))

print(sorted_words)Code language: Python (python)

Explanation:

  • words.items(): Produces pairs like [("a", "banana"), ("b", "kiwi"), ...] that sorted() can iterate over.
  • lambda item: len(item[1]): For each pair, extracts the value (item[1]) and returns its character count. sorted() uses this count as the sort key.
  • dict(...): Reconstructs the dictionary from the now-ordered list of tuples. The insertion order is maintained in Python 3.7+.
  • Note: If two values share the same length, their relative order depends on their original position in the dictionary (stable sort behavior).

Exercise 33: Key with Longest List

Problem Statement: Write a Python program to find the key in a dictionary whose associated list value has the greatest number of elements.

Purpose: This exercise helps you practice using max() with a custom key on dictionary items, working with list values, and extracting meaningful information from nested data structures – patterns common in analytics and data aggregation.

Given Input: data = {"fruits": ["apple", "banana", "cherry"], "vegs": ["carrot"], "grains": ["rice", "wheat"]}

Expected Output: fruits

▼ Hint
  • Use max() on dict.items() with a key argument.
  • The key lambda should return len(item[1]) – the length of each list value.
  • max() returns the full key-value tuple, so use index [0] to extract just the key.
▼ Solution & Explanation

Solution:

data = {"fruits": ["apple", "banana", "cherry"], "vegs": ["carrot"], "grains": ["rice", "wheat"]}

longest_key = max(data.items(), key=lambda item: len(item[1]))[0]

print(longest_key)Code language: Python (python)

Explanation:

  • data.items(): Provides all key-value pairs. Each value here is a list, e.g., ("fruits", ["apple", "banana", "cherry"]).
  • key=lambda item: len(item[1]): Instructs max() to compare items by the length of their list values rather than by the keys themselves.
  • [0]: max() returns the winning tuple, e.g., ("fruits", [...]). Indexing with [0] pulls out just the key name.
  • Note: If two keys have lists of equal maximum length, max() returns whichever appears first during iteration.

Exercise 34: Convert Dictionary to JSON

Problem Statement: Write a Python program to convert a nested dictionary into a formatted JSON string with readable indentation.

Purpose: This exercise helps you practice using Python’s built-in json module, serializing complex data structures, and controlling output formatting – skills essential for APIs, configuration files, and data interchange between systems.

Given Input: person = {"name": "Alice", "age": 30, "address": {"city": "Mumbai", "pin": "400001"}}

Expected Output:

{
    "name": "Alice",
    "age": 30,
    "address": {
        "city": "Mumbai",
        "pin": "400001"
    }
}
▼ Hint

Import the json module and use json.dumps() with the indent parameter set to 4 to produce a nicely formatted string.

▼ Solution & Explanation

Solution:

import json

person = {"name": "Alice", "age": 30, "address": {"city": "Mumbai", "pin": "400001"}}

json_string = json.dumps(person, indent=4)

print(json_string)Code language: Python (python)

Explanation:

  • import json: Loads Python’s standard library module for JSON encoding and decoding – no installation needed.
  • json.dumps(person, indent=4): Serializes the dictionary to a JSON-formatted string. The indent=4 argument adds 4-space indentation at each nesting level for human-readable output.
  • Nested structure: The address key holds another dictionary. json.dumps() handles nested structures recursively, so no extra steps are needed.
  • Alternative: Use json.dump(person, file_object, indent=4) to write the JSON directly to a file instead of returning a string.

Exercise 35: Invert Dictionary

Problem Statement: Write a Python program to invert a dictionary by swapping its keys and values, so each original value becomes a key and each original key becomes the corresponding value.

Purpose: This exercise helps you practice dictionary comprehensions, understanding key uniqueness constraints, and transforming data structures – a technique used in reverse lookups, encoding/decoding maps, and symbol tables.

Given Input: original = {"a": 1, "b": 2, "c": 3}

Expected Output: {1: "a", 2: "b", 3: "c"}

▼ Hint
  • Use a dictionary comprehension with original.items() to iterate over key-value pairs.
  • In the comprehension, set the value as the new key and the key as the new value: {v: k for k, v in original.items()}.
  • This only works correctly when all original values are unique and hashable. Duplicate values would cause key collisions.
▼ Solution & Explanation

Solution:

original = {"a": 1, "b": 2, "c": 3}

inverted = {v: k for k, v in original.items()}

print(inverted)Code language: Python (python)

Explanation:

  • original.items(): Returns each key-value pair as a tuple, e.g., ("a", 1), which is unpacked into k and v in the comprehension.
  • {v: k for k, v in ...}: Builds a new dictionary where each original value v becomes a key and each original key k becomes the value – a clean one-line inversion.
  • Key constraint: Dictionary keys must be unique and hashable. If two keys in original share the same value, only the last one survives in the inverted dictionary.
  • Alternative: Use dict(zip(original.values(), original.keys())) for an equivalent result without a comprehension.

Exercise 36: Invert with Duplicate Values

Problem Statement: Write a Python program to invert a dictionary where multiple keys may share the same value. Instead of overwriting, group all original keys that map to the same value into a list under that value as the new key.

Purpose: This exercise helps you practice handling collisions during dictionary inversion, using setdefault() or defaultdict, and building grouped structures from flat data – a pattern common in indexing, tagging systems, and reverse lookups.

Given Input: original = {"a": 1, "b": 2, "c": 1, "d": 3, "e": 2}

Expected Output: {1: ["a", "c"], 2: ["b", "e"], 3: ["d"]}

▼ Hint
  • Start with an empty dictionary for the inverted result.
  • Loop over original.items() and for each key-value pair, use the value as the new key.
  • Use setdefault(v, []) to initialize an empty list the first time a value is seen, then .append(k) to add the original key to it.
▼ Solution & Explanation

Solution:

original = {"a": 1, "b": 2, "c": 1, "d": 3, "e": 2}

inverted = {}
for k, v in original.items():
    inverted.setdefault(v, []).append(k)

print(inverted)Code language: Python (python)

Explanation:

  • original.items(): Yields each key-value pair in turn, e.g., ("a", 1), ("b", 2), ("c", 1), and so on.
  • inverted.setdefault(v, []): Checks if v already exists as a key in inverted. If not, it inserts it with an empty list as the default value and returns that list either way.
  • .append(k): Adds the original key to the list associated with that value, so all keys sharing the same value are collected together.
  • Alternative: Use collections.defaultdict(list) and replace setdefault with a direct inverted[v].append(k) for slightly cleaner syntax.

Exercise 37: Flatten Nested Dictionary

Problem Statement: Write a Python program to flatten a multi-level nested dictionary into a single-level dictionary, joining nested keys with a dot separator to form the new keys.

Purpose: This exercise helps you practice recursive thinking, string key construction, and traversing nested data structures – skills used in configuration parsing, JSON flattening for databases, and working with API responses.

Given Input: nested = {"a": 1, "b": {"c": 2, "d": {"e": 3, "f": 4}}}

Expected Output: {"a": 1, "b.c": 2, "b.d.e": 3, "b.d.f": 4}

▼ Hint
  • Define a recursive helper function that accepts the current dictionary and a prefix string (empty at the top level).
  • For each key-value pair, build a new key by joining the prefix and the current key with a dot.
  • If the value is itself a dictionary, recurse into it. Otherwise, store the new key and value in the result dictionary.
▼ Solution & Explanation

Solution:

nested = {"a": 1, "b": {"c": 2, "d": {"e": 3, "f": 4}}}

def flatten(d, prefix=""):
    result = {}
    for k, v in d.items():
        new_key = f"{prefix}.{k}" if prefix else k
        if isinstance(v, dict):
            result.update(flatten(v, new_key))
        else:
            result[new_key] = v
    return result

print(flatten(nested))Code language: Python (python)

Explanation:

  • prefix="": The default empty string means top-level keys get no dot prepended. As recursion deepens, the prefix carries the accumulated path of parent keys.
  • new_key = f"{prefix}.{k}" if prefix else k: Builds the dotted path for the current key. At the top level it is just k; at deeper levels it becomes something like b.d.
  • isinstance(v, dict): Checks whether the current value is another dictionary. If so, the function calls itself with the nested dict and the updated prefix, then merges the results with result.update().
  • Base case: When the value is not a dictionary, it is a leaf node and gets stored directly under its fully qualified key.

Exercise 38: Group by First Letter

Problem Statement: Write a Python program to organize a list of words into a dictionary where each key is a starting letter and the corresponding value is a list of all words beginning with that letter.

Purpose: This exercise helps you practice grouping data with dictionaries, using setdefault(), and building index-like structures – techniques commonly used in autocomplete engines, glossaries, and search indexing.

Given Input: words = ["apple", "avocado", "banana", "blueberry", "cherry", "apricot"]

Expected Output:

{"a": ["apple", "avocado", "apricot"], "b": ["banana", "blueberry"], "c": ["cherry"]}
▼ Hint
  • Start with an empty dictionary.
  • Loop over the words list and extract the first character of each word using index [0].
  • Use setdefault(letter, []) to create an empty list for new letters, then .append(word) to add the word.
▼ Solution & Explanation

Solution:

words = ["apple", "avocado", "banana", "blueberry", "cherry", "apricot"]

grouped = {}
for word in words:
    letter = word[0]
    grouped.setdefault(letter, []).append(word)

print(grouped)Code language: Python (python)

Explanation:

  • word[0]: Extracts the first character of each word, which serves as the grouping key. For "apple" this yields "a", for "banana" it yields "b", and so on.
  • grouped.setdefault(letter, []): Returns the existing list for that letter if it already exists, or inserts a fresh empty list and returns it if the letter is seen for the first time.
  • .append(word): Adds the current word to the correct group. Because setdefault returns the list in place, the append operates directly on the stored list.
  • Alternative: collections.defaultdict(list) removes the need for setdefault: just write grouped[letter].append(word) directly.

Exercise 39: Merge and Sum Overlapping

Problem Statement: Write a Python program to merge two dictionaries such that when both share the same key, their values are added together rather than one overwriting the other.

Purpose: This exercise helps you practice dictionary merging strategies, iterating over items, and handling key conflicts deliberately – skills useful in inventory systems, vote tallying, word frequency counting, and financial aggregation.

Given Input: dict1 = {"a": 10, "b": 20, "c": 30} and dict2 = {"b": 5, "c": 15, "d": 25}

Expected Output: {"a": 10, "b": 25, "c": 45, "d": 25}

▼ Hint
  • Start by copying dict1 into the result using dict1.copy() to avoid modifying the original.
  • Loop over dict2.items() and for each key, add the value to the result if the key already exists, or insert it fresh if it does not.
  • Use result.get(k, 0) to safely retrieve an existing value with a fallback of zero before adding.
▼ Solution & Explanation

Solution:

dict1 = {"a": 10, "b": 20, "c": 30}
dict2 = {"b": 5, "c": 15, "d": 25}

merged = dict1.copy()
for k, v in dict2.items():
    merged[k] = merged.get(k, 0) + v

print(merged)Code language: Python (python)

Explanation:

  • dict1.copy(): Creates a shallow copy of dict1 as the starting point so the original dictionary is not modified during the merge.
  • merged.get(k, 0): Retrieves the current value for key k from merged, defaulting to 0 if the key is not yet present. This makes the addition safe for both overlapping and new keys.
  • merged[k] = ... + v: Stores the summed result back. For shared keys like "b", this gives 20 + 5 = 25. For new keys like "d", it gives 0 + 25 = 25.
  • Alternative: collections.Counter supports addition directly: Counter(dict1) + Counter(dict2) produces the same result in one line.

Exercise 40: Deep vs. Shallow Copy

Problem Statement: Write a Python program that demonstrates the difference between a shallow copy and a deep copy of a dictionary containing nested lists, showing how changes to nested data affect each copy differently.

Purpose: This exercise helps you understand how Python manages object references, why mutating nested structures in a shallow copy also affects the original, and when to use copy.deepcopy() – critical knowledge for avoiding hard-to-trace bugs in data processing and state management.

Given Input: original = {"name": "Alice", "scores": [90, 85, 92]}

Expected Output:

Shallow copy scores: [90, 85, 92, 100]
Original scores after shallow mutation: [90, 85, 92, 100]

Deep copy scores: [90, 85, 92, 99]
Original scores after deep mutation: [90, 85, 92, 100]
▼ Hint
  • Use dict.copy() or copy.copy() to create a shallow copy.
  • Import the copy module and use copy.deepcopy() to create a fully independent copy.
  • After each copy, append a value to the nested scores list and print both the copy and the original to observe which one is affected.
▼ Solution & Explanation

Solution:

import copy

original = {"name": "Alice", "scores": [90, 85, 92]}

# Shallow copy
shallow = original.copy()
shallow["scores"].append(100)
print("Shallow copy scores:", shallow["scores"])
print("Original scores after shallow mutation:", original["scores"])

print()

# Restore original for a clean deep copy demo
original = {"name": "Alice", "scores": [90, 85, 92, 100]}

# Deep copy
deep = copy.deepcopy(original)
deep["scores"].append(99)
print("Deep copy scores:", deep["scores"])
print("Original scores after deep mutation:", original["scores"])Code language: Python (python)

Explanation:

  • original.copy(): Creates a new dictionary with the same top-level keys, but the values are not duplicated. The scores list in the shallow copy is the exact same list object in memory as the one in original.
  • Shallow mutation effect: Appending 100 to shallow["scores"] modifies the shared list, so original["scores"] reflects the same change. This is the key risk of shallow copies with mutable nested values.
  • copy.deepcopy(original): Recursively duplicates every object at every level. The scores list in deep is a brand-new list with no connection to the original.
  • Deep mutation effect: Appending 99 to deep["scores"] has no impact on original["scores"], confirming full independence between the two copies.

Filed Under: Python, Python Basics, Python Exercises

Did you find this page helpful? Let others know about it. Sharing helps me continue to create free Python resources.

TweetF  sharein  shareP  Pin

About Vishal

I’m Vishal Hule, the Founder of PYnative.com. As a Python developer, I enjoy assisting students, developers, and learners. Follow me on Twitter.

Related Tutorial Topics:

Python Python Basics Python Exercises

All Coding Exercises:

C Exercises
C++ Exercises
Python Exercises

Python Exercises and Quizzes

Free coding exercises and quizzes cover Python basics, data structure, data analytics, and more.

  • 15+ Topic-specific Exercises and Quizzes
  • Each Exercise contains 25+ questions
  • Each Quiz contains 25 MCQ
Exercises
Quizzes

Loading comments... Please wait.

In: Python Python Basics Python Exercises
TweetF  sharein  shareP  Pin

  Python Exercises

  • All Python Exercises
  • Basic Exercise for Beginners
  • Intermediate Python Exercises
  • Input and Output Exercise
  • Loop Exercise
  • Functions Exercise
  • String Exercise
  • Data Structure Exercise
  • List Exercise
  • Dictionary Exercise
  • Set Exercise
  • Tuple Exercise
  • Date and Time Exercise
  • OOP Exercise
  • File Handling Exercise
  • Python JSON Exercise
  • Random Data Generation Exercise
  • NumPy Exercise
  • Pandas Exercise
  • Matplotlib Exercise
  • Python Database Exercise

 Explore Python

  • Python Tutorials
  • Python Exercises
  • Python Quizzes
  • Python Interview Q&A
  • Python Programs

All Python Topics

Python Basics Python Exercises Python Quizzes Python Interview Python File Handling Python OOP Python Date and Time Python Random Python Regex Python Pandas Python Databases Python MySQL Python PostgreSQL Python SQLite Python JSON

About PYnative

PYnative.com is for Python lovers. Here, You can get Tutorials, Exercises, and Quizzes to practice and improve your Python skills.

Follow Us

To get New Python Tutorials, Exercises, and Quizzes

  • Twitter
  • Facebook
  • Sitemap

Explore Python

  • Learn Python
  • Python Basics
  • Python Databases
  • Python Exercises
  • Python Quizzes
  • Online Python Code Editor
  • Python Tricks

Coding Exercises

  • C Exercises
  • C++ Exercises
  • Python Exercises

Legal Stuff

  • About Us
  • Contact Us

We use cookies to improve your experience. While using PYnative, you agree to have read and accepted our:

  • Terms Of Use
  • Privacy Policy
  • Cookie Policy

Copyright © 2018–2026 pynative.com