Week 6: Dictionaries
2333 words
12 min read
Visual companion
Python
Type and operator map
Python Week 1: the first filter for runtime behavior
View
Revision summary
What this note is really saying
Short form
# Week 6: Dictionaries > **BSCS1001 — IIT Madras BS Degree** **Prerequisite:** Week 5 (Lists) **Cross-links:** BSCS1002-Python (Week 8 — Dictionaries), BSCS2002-PDSA (Week 3 — Map ADT) ## 1. Motivation: Beyond Lists Lists are great for sequences, but they have a limitation: **you can't quickly find an element by its...

Week 6: Dictionaries
BSCS1001 — IIT Madras BS Degree Prerequisite: Week 5 (Lists) Cross-links: BSCS1002-Python (Week 8 — Dictionaries), BSCS2002-PDSA (Week 3 — Map ADT)
1. Motivation: Beyond Lists
Lists are great for sequences, but they have a limitation: you can't quickly find an element by its value.
| Problem | With List | With Dictionary |
|---|---|---|
| "What is Alice's Chemistry mark?" | Scan the whole list to find Alice | chemMarks["Alice"] — instant! |
| "Count students per city" | Build multiple lists, nested searches | Use city name as key, count as value |
| "Find duplicates by birthday" | Nested iteration (O(N²)) | Dictionary lookup (O(N)) |
Real-world analogy: A list is like a row of lockers numbered 0, 1, 2... You must walk down the row to find something. A dictionary is like a phonebook — you look up the name (key) and instantly get the number (value).
2. What is a Dictionary?
A dictionary stores key-value pairs. You provide a key, and the dictionary returns the associated value.
Syntax
pseudo// Creating a dictionary d = {} // Adding key-value pairs d["Rahul"] = 92 d["Ritika"] = 89 // Accessing values marks = d["Rahul"] // marks = 92
Visual Representation
(Diagram)
Key Properties
| Property | Description |
|---|---|
| Key-value pairs | Each entry maps a key to a value |
| Unique keys | Each key appears at most once |
| Unordered | Keys are not stored in any particular order |
| Random access | Get any value instantly by key |
| Dynamic | Can add and remove keys |
Dictionary vs Record
| Aspect | Record | Dictionary |
|---|---|---|
| Fields | Fixed at design time | Dynamic (add any key) |
| Field names | Known in advance | Can be data values |
| Schema | Rigid | Flexible |
| Example | X.Name, X.Maths | d["Rahul"], d["Ritika"] |
3. Dictionary Operations
Core Operations
| Operation | Syntax | Example | Description |
|---|---|---|---|
| Create empty | d = {} | marks = {} | New empty dictionary |
| Assign value | d[key] = value | d["Rahul"] = 92 | Creates or updates entry |
| Get value | d[key] | m = d["Rahul"] | Returns value for key |
| Check key | isKey(d, k) | if isKey(d, "Rahul") | True if key exists |
| List keys | keys(d) | for k in keys(d) | List of all keys |
| Delete key | (see below) | — | Remove a key-value pair |
Assigning Values
pseudo// First assignment — creates the entry chemMarks["Rahul"] = 92 // Re-assignment — updates the value chemMarks["Rahul"] = 95 // Now Rahul's mark is 95 // Incrementing a value chemMarks["Rahul"] = chemMarks["Rahul"] + 5 // Now 100
Keys Must Be Unique
pseudod = {} d["Alice"] = 85 d["Alice"] = 90 // Overwrites! Now d["Alice"] = 90
Common Gotcha: Key Doesn't Exist
pythond = {"Rahul": 92} print(d["Ritika"]) // ERROR! "Ritika" is not a key
Always check with
isKey before accessing:pythonif (isKey(d, "Ritika")) { print(d["Ritika"]) } else { print("Key not found") }
4. Building Dictionaries
Pattern: Collect Data from Dataset
pseudod = {} while (Table 1 has more rows) { Read the first row X in Table 1 key = some field of X value = some other field of X d[key] = value Move X to Table 2 }
Example: Chemistry Marks Dictionary
pseudochemMarks = {} while (Table 1 has more rows) { Read the first row X in Table 1 name = X.Name marks = X.ChemistryMarks chemMarks[name] = marks Move X to Table 2 }
Dataset:
| Name | Chemistry |
|---|---|
| Rahul | 92 |
| Ritika | 89 |
| Amit | 78 |
Result:
chemMarks = {"Rahul": 92, "Ritika": 89, "Amit": 78}Example: Counting with Dictionaries
sql// Count how many students from each city cityCount = {} while (Table 1 has more rows) { Read the first row X in Table 1 city = X.City if (isKey(cityCount, city)) { cityCount[city] = cityCount[city] + 1 } else { cityCount[city] = 1 } Move X to Table 2 }
Tracing with dataset [Chennai, Mumbai, Chennai, Delhi, Chennai]:
| Card | City | isKey? | cityCount After |
|---|---|---|---|
| 1 | Chennai | ❌ New | {"Chennai": 1} |
| 2 | Mumbai | ❌ New | {"Chennai": 1, "Mumbai": 1} |
| 3 | Chennai | ✅ Yes | {"Chennai": 2, "Mumbai": 1} |
| 4 | Delhi | ❌ New | {"Chennai": 2, "Mumbai": 1, "Delhi": 1} |
| 5 | Chennai | ✅ Yes | {"Chennai": 3, "Mumbai": 1, "Delhi": 1} |
Final:
{"Chennai": 3, "Mumbai": 1, "Delhi": 1}5. Processing Dictionaries
Iterating Through Keys
pseudoforeach k in keys(d) { // Do something with d[k] }
Example: Compute Average
pseudototal = 0 count = 0 foreach k in keys(chemMarks) { total = total + chemMarks[k] count = count + 1 } average = total / count
Example: Find Max Value
pseudomaxMark = 0 topStudent = "" foreach k in keys(chemMarks) { if (chemMarks[k] > maxMark) { maxMark = chemMarks[k] topStudent = k } }
Example: Filter Students Above Threshold
pseudoabove80 = [] foreach k in keys(chemMarks) { if (chemMarks[k] > 80) { above80 = above80 ++ [k] } }
6. isKey Operation
What isKey Does
isKey(d, k) returns True if k is a key in dictionary d, False otherwise.How isKey Works (Conceptual)
pseudoProcedure isKey(d, k) found = False foreach key in keys(d) { if (key == k) { found = True exitloop } } return(found) End isKey
Important: In our course, we assumeisKeyis provided as a built-in operation that works in constant time (instant lookup), not by scanning all keys.
Typical Usage Pattern
pseudo// Add to count if key exists, otherwise create if (isKey(runs, "Kohli")) { runs["Kohli"] = runs["Kohli"] + score } else { runs["Kohli"] = score }
7. Birthday Paradox with Dictionaries
This is the most elegant solution — much better than nested iterations or binning.
Algorithm
pseudoProcedure FindSharedBirthdays() { birthdays = {} duplicates = {} while (Table 1 has more rows) { Read the first row X in Table 1 dob = X.Dob seqno = X.SeqNo if (isKey(birthdays, dob)) { // This birthday already seen — mark as duplicate duplicates[dob] = True // Store student under this birthday birthdays[dob][seqno] = True } else { // First time seeing this birthday birthdays[dob] = {} birthdays[dob][seqno] = True } Move X to Table 2 } return(duplicates) End FindSharedBirthdays
How It Works (with Nested Dictionary)
The
birthdays dictionary maps: birthday → {student IDs}pseudobirthdays = { 45: {101: True, 103: True}, // Two students born on day 45 120: {102: True, 105: True}, // Two students born on day 120 200: {104: True} // One student born on day 200 }
The
duplicates dictionary just tracks which birthdays have >1 student.Tracing
Dataset:
| SeqNo | DOB |
|---|---|
| 101 | 45 |
| 102 | 120 |
| 103 | 45 |
| 104 | 200 |
| 105 | 120 |
| Row | SeqNo | DOB | isKey? | birthdays | duplicates |
|---|---|---|---|---|---|
| 1 | 101 | 45 | ❌ | {45: {101: True}} | {} |
| 2 | 102 | 120 | ❌ | {45: {101}, 120: {102}} | {} |
| 3 | 103 | 45 | ✅ | {45: {101, 103}, 120: {102}} | {45: True} |
| 4 | 104 | 200 | ❌ | {..., 200: {104}} | {45: True} |
| 5 | 105 | 120 | ✅ | {..., 120: {102, 105}} | {45: True, 120: True} |
Result: Duplicates found for DOBs 45 and 120.
Complexity: O(N) — Linear!
No nested iteration needed! Just one pass through the data. This is the power of dictionaries.
8. Dictionary Applications
Customer Spending Analysis
pseudo// Build dictionary: customer → total spending spending = {} while (Table 1 has more rows) { Read the first row X in Table 1 customer = X.CustomerName amount = X.Amount if (isKey(spending, customer)) { spending[customer] = spending[customer] + amount } else { spending[customer] = amount } Move X to Table 2 }
Pronoun Resolution
Track nouns and pronouns by their position, then match them:
pseudopartOfSpeech = {} partOfSpeech["Noun"] = [] partOfSpeech["Pronoun"] = [] while (Table 1 has more rows) { Read the first row X in Table 1 if (X.PartOfSpeech == "Noun") { partOfSpeech["Noun"] = partOfSpeech["Noun"] ++ [X.SerialNo] } if (X.PartOfSpeech == "Pronoun") { partOfSpeech["Pronoun"] = partOfSpeech["Pronoun"] ++ [X.SerialNo] } Move X to Table 2 } // Now match each pronoun to nearest preceding noun matchD = {} foreach p in partOfSpeech["Pronoun"] { matched = -1 foreach n in partOfSpeech["Noun"] { if (n < p) { matched = n } else { exitloop // Nouns are sorted, no need to continue } } matchD[p] = matched }
Food Items Analysis
pseudo// Count food items per customer foodD = {} while (Table 1 has more rows) { Read the first row X in Table 1 customer = X.CustomerName items = X.Items for each row in items { if (row.Category == "Food") { if (isKey(foodD, customer)) { foodD[customer] = foodD[customer] + 1 } else { foodD[customer] = 1 } } } Move X to Table 2 }
9. Comparison: List vs Dictionary
List vs Dictionary
| Aspect | List | Dictionary |
|---|---|---|
| Access | By position (index) | By key |
| Order | Maintains insertion order | Unordered |
| Speed: lookup by value | O(N) — must scan | O(1) — instant |
| Speed: iteration | O(N) — linear | O(N) — linear |
| Keys must be unique? | N/A (positions are unique) | Yes |
| Use case | Sequences, ordered data | Lookups, mappings, counting |
When to Use What
(Diagram)
Converting Between List and Dictionary
pseudo// List of keys → dictionary with True values students = ["Rahul", "Ritika", "Amit"] studentDict = {} foreach s in students { studentDict[s] = True } // Now: if (isKey(studentDict, "Rahul")) is instant
10. Practice Questions
Basic Questions
Q1. What is a dictionary? What are its two main components?
Show AnswerA dictionary stores key-value pairs. Each entry has a key (used to look up) and a value (the data stored). Keys must be unique. Q2. What doesisKey(d, k)do? Show AnswerisKey(d, k)checks ifkexists as a key in dictionaryd. It returnsTrueif the key exists,Falseotherwise. Q3. Write pseudocode to create a dictionary that stores students' ages (name → age). Show Answerpseudoages = {} ages["Alice"] = 20 ages["Bob"] = 22 ages["Charlie"] = 19
Q4. What is the advantage of using a dictionary over nested iterations for finding shared birthdays?
Show AnswerWith nested iterations, finding shared birthdays requires O(N²) comparisons. With a dictionary, we can do it in O(N) — a single pass through the data. Dictionaries provide instant (O(1)) lookup by key, eliminating the need for pairwise comparisons.
Intermediate Questions
Q5. Trace this pseudocode:
pseudod = {} d["x"] = 10 d["y"] = 20 d["x"] = d["x"] + 5 d["z"] = d["x"] + d["y"]
What is d at the end?
Show Answer
| Step | Statement | d After |
|---|---|---|
| 1 | d = {} | {} |
| 2 | d["x"] = 10 | {"x": 10} |
| 3 | d["y"] = 20 | {"x": 10, "y": 20} |
| 4 | d["x"] = 10 + 5 = 15 | {"x": 15, "y": 20} |
| 5 | d["z"] = 15 + 20 = 35 | {"x": 15, "y": 20, "z": 35} |
Final:{"x": 15, "y": 20, "z": 35}Q6. Write pseudocode to find the student with the highest Chemistry mark using a dictionary. Show AnswerpseudochemMarks = {"Rahul": 92, "Ritika": 89, "Amit": 78, "Priya": 95} maxMark = 0 topStudent = "" foreach k in keys(chemMarks) { if (chemMarks[k] > maxMark) { maxMark = chemMarks[k] topStudent = k } } // topStudent = "Priya", maxMark = 95
Q7. Explain the difference between a record's field access (X.Name) and a dictionary's key access (d["Name"]).
Show Answer
- Record field:
X.Name— the field name is fixed at design time. You must know the field name when writing the code.- Dictionary key:
d["Name"]— the key can be any value, including data read at runtime. You can use variables as keys.Dictionaries are more flexible because keys can be computed dynamically. Q8. What happens if you access a key that doesn't exist in a dictionary? How do you avoid this? Show AnswerAccessing a non-existent key causes an error. To avoid this, always check withisKeyfirst:pseudoif (isKey(d, someKey)) { value = d[someKey] // Safe! } else { // Handle missing key }
Advanced Questions
Q9. Write a procedure that takes two dictionaries and returns a new dictionary containing keys present in BOTH. The values should be from the first dictionary.
Show AnswerpseudoProcedure DictIntersection(d1, d2) { result = {} foreach k in keys(d1) { if (isKey(d2, k)) { result[k] = d1[k] } } return(result) End DictIntersection // Example: // d1 = {"a": 1, "b": 2, "c": 3} // d2 = {"b": 20, "c": 30, "d": 40} // Result: {"b": 2, "c": 3}
Q10. Use a dictionary to find the most frequently occurring word in a paragraph.
Show AnswerpseudowordCount = {} while (Pile 1 has more cards) { Pick a card X word = X.Word if (isKey(wordCount, word)) { wordCount[word] = wordCount[word] + 1 } else { wordCount[word] = 1 } } // Find most frequent maxCount = 0 mostFreq = "" foreach w in keys(wordCount) { if (wordCount[w] > maxCount) { maxCount = wordCount[w] mostFreq = w } }
Q11. Compare the three approaches to the birthday paradox: nested iteration, binning, and dictionary. Which is best and why?
Show Answer
| Approach | Complexity | Ease | Best For |
|---|---|---|---|
| Nested iteration | O(N²) | Simple | Small N (< 100) |
| Binning | O(N²/K) | Moderate | Medium N, natural bins |
| Dictionary | O(N) | Easy | Any N, especially large |
Best: Dictionary approach. It's simple, requires only one pass through the data (O(N)), and doesn't need pre-defined bins or nested loops. The key insight is using the birthday as the key and checking for duplicates viaisKey. Q12. Write pseudocode to create a dictionary where each key maps to a LIST of values (e.g., students per city). Show AnswerpseudocityStudents = {} while (Table 1 has more rows) { Read the first row X in Table 1 city = X.City student = X.Name if (isKey(cityStudents, city)) { // Append to existing list cityStudents[city] = cityStudents[city] ++ [student] } else { // Create new list cityStudents[city] = [student] } Move X to Table 2 } // Result: {"Chennai": ["Rahul", "Priya"], "Mumbai": ["Amit"]}
📚 Cross-References
| Course | Topic | Connection |
|---|---|---|
| BSCS1002 (Python) | Week 8 — Dictionaries | Python dict, keys(), in |
| BSCS2002 (PDSA) | Week 3 — Map ADT | Dictionary as abstract data type |
| BSCS2002 (PDSA) | Week 7 — Hashing | How dictionaries achieve O(1) lookup |
Next Topic: 12 — Dictionary ApplicationsQuiz Tip: Birthday paradox with dictionaries is a classic — understand it thoroughly! Join Discord PreviousInsertion SortNextDictionary Applications