Level 2 / Project 02 - Nested Data Flattener¶
Home: README
Try in Browser: Run this exercise online — no installation needed!
Before You Start¶
Recall these prerequisites before diving in:
- Can you use isinstance() to check if a value is a dict or a list?
- Can you explain what recursion is? (A function that calls itself)
Estimated time: 30 minutes
Learn Your Way¶
| Read | Build | Watch | Test | Review | Visualize | Try |
|---|---|---|---|---|---|---|
| Concept | This project | — | Quiz | Flashcards | Diagram | Browser |
Focus¶
- flatten lists/dicts to row structures
Why this project exists¶
This project gives you level-appropriate practice in a realistic operations context. Goal: run the baseline, alter behavior, break one assumption, recover safely, and explain the fix.
Run (copy/paste)¶
Use <repo-root> as the folder containing this repository's README.md.
cd <repo-root>/projects/level-2/02-nested-data-flattener
python project.py data/sample_input.txt
python project.py data/sample_input.txt --separator /
pytest -q
Expected terminal output¶
Expected artifacts¶
- Flattened JSON on stdout
- Passing tests
- Updated
notes.md
Worked Example¶
Here is a similar (but different) problem, solved step by step.
Problem: Write a function that flattens a nested list into a single list. [1, [2, [3, 4]], 5] becomes [1, 2, 3, 4, 5].
Step 1: Think recursively. For each item: if it is a list, flatten it. If it is not a list, add it to the result.
def flatten_list(nested):
result = []
for item in nested:
if isinstance(item, list):
result.extend(flatten_list(item)) # recurse
else:
result.append(item)
return result
Step 2: Trace it on paper. flatten_list([1, [2, [3]]]):
- item 1: not a list, append. result = [1]
- item [2, [3]]: is a list, recurse:
- item 2: not a list, append. result = [2]
- item [3]: is a list, recurse:
- item 3: not a list, append. result = [3]
- extend with [3]. result = [2, 3]
- extend with [2, 3]. result = [1, 2, 3]
The thought process: Recursion handles arbitrary nesting depth because each level calls the same function. The dict flattener project uses the same approach but builds dot-separated keys instead of a flat list.
Checkpoint: Baseline code runs and all tests pass. Commit your work before continuing.
Alter it (required) — Extension¶
- Add a
--max-depthflag that stops flattening beyond N levels. - Change the separator to
__(double underscore) and observe the output. - Add a
--keys-onlyflag that prints just the flattened key names.
Break it (required) — Core¶
- Pass a JSON file whose root is a list
[1, 2, 3]— what error appears? - Create a key that already contains a dot, e.g.
{"a.b": 1}— what happens? - Flatten then unflatten a structure with lists — is the roundtrip perfect?
Fix it (required) — Core¶
- Add a guard in
flatten_from_filefor non-dict JSON roots. - Handle keys that contain the separator character (escape or warn).
- Add a test for empty dict input
{}.
Checkpoint: All modifications done, tests still pass. Good time to review your changes.
Explain it (teach-back)¶
- What is recursion and why is it useful for nested data?
- How does
isinstance(value, dict)decide the recursion path? - Why might flattening lose information about list vs. dict structure?
- Where would you use flatten/unflatten in real DevOps or data pipelines?
Mastery check¶
You can move on when you can:
- trace the recursion for a 3-level nested dict on paper,
- explain the difference between dict.update() and dict[key] = value,
- add support for a new data type (e.g. sets) without breaking existing tests,
- describe when flattening is useful vs. when it loses information.
Related Concepts¶
- Collections Explained
- Functions Explained
- How Loops Work
- Types and Conversions
- Quiz: Collections Explained
Stuck? Ask AI¶
If you are stuck after trying for 20 minutes, use one of these prompts:
- "I am working on Nested Data Flattener. I got this error: [paste error]. Can you explain what this error means without giving me the fix?"
- "I am trying to understand recursion. Can you trace through a recursive function call step by step, using a simple example like factorial?"
- "Can you explain how
isinstance(value, dict)works and when to use it instead oftype(value) == dict?"
| ← Prev | Home | Next → |
|---|---|---|