Skip to content

05-07: zip(), enumerate(), and Collection Conversions


enumerate() — Index + Value Together

enumerate() wraps an iterable and yields (index, value) pairs:

fruits = ["apple", "banana", "cherry"]

# Basic usage
for i, fruit in enumerate(fruits):
    print(i, fruit)
# 0 apple
# 1 banana
# 2 cherry

# Start numbering from 1
for i, fruit in enumerate(fruits, start=1):
    print(f"{i}. {fruit}")
# 1. apple
# 2. banana
# 3. cherry

Why enumerate instead of range(len())?

# Old (verbose) way
for i in range(len(fruits)):
    print(i, fruits[i])

# Pythonic way — enumerate is cleaner
for i, fruit in enumerate(fruits):
    print(i, fruit)

enumerate() with any iterable

# With string
for i, char in enumerate("hello"):
    print(f"Index {i}: {char}")

# With dict
d = {"a": 1, "b": 2, "c": 3}
for i, key in enumerate(d):
    print(f"Item #{i}: {key} = {d[key]}")

# Convert enumerate to list of tuples
result = list(enumerate(["x", "y", "z"]))
print(result)   # [(0, 'x'), (1, 'y'), (2, 'z')]

# Build indexed dict
words = ["zero", "one", "two", "three"]
num_to_word = dict(enumerate(words))
print(num_to_word)   # {0: 'zero', 1: 'one', 2: 'two', 3: 'three'}

zip() — Parallel Iteration

zip() combines multiple iterables element-by-element:

names  = ["Alice", "Bob", "Charlie"]
scores = [85, 92, 78]

for name, score in zip(names, scores):
    print(f"{name}: {score}")
# Alice: 85
# Bob: 92
# Charlie: 78

zip() stops at the shortest iterable

a = [1, 2, 3, 4, 5]
b = ["a", "b", "c"]

for x, y in zip(a, b):
    print(x, y)
# 1 a
# 2 b
# 3 c
# (stops at length of shorter iterable)

Three or more iterables

names  = ["Alice", "Bob", "Charlie"]
scores = [85, 92, 78]
grades = ["B", "A", "C"]

for name, score, grade in zip(names, scores, grades):
    print(f"{name}: {score} ({grade})")
# Alice: 85 (B)
# Bob: 92 (A)
# Charlie: 78 (C)

Building a dict with zip()

keys   = ["name", "age", "city"]
values = ["Alice", 30, "New York"]

d = dict(zip(keys, values))
print(d)   # {'name': 'Alice', 'age': 30, 'city': 'New York'}

# Two lists → dict
students = ["Alice", "Bob", "Charlie"]
grades   = ["A", "B", "A+"]
grade_dict = dict(zip(students, grades))
print(grade_dict)   # {'Alice': 'A', 'Bob': 'B', 'Charlie': 'A+'}

Unzipping — transpose pairs

pairs = [(1, "a"), (2, "b"), (3, "c")]

# Unzip using *
numbers, letters = zip(*pairs)
print(numbers)   # (1, 2, 3)
print(letters)   # ('a', 'b', 'c')

# Transposing a matrix
matrix = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]
transposed = list(zip(*matrix))
print(transposed)
# [(1, 4, 7), (2, 5, 8), (3, 6, 9)]

zip_longest() — pad shorter iterables

from itertools import zip_longest

a = [1, 2, 3]
b = ["a", "b"]

for x, y in zip_longest(a, b, fillvalue=None):
    print(x, y)
# 1 a
# 2 b
# 3 None

Converting Between Collection Types

list(), tuple(), set() — Universal Converters

# Range → list / tuple / set
print(list(range(5)))          # [0, 1, 2, 3, 4]
print(tuple(range(5)))         # (0, 1, 2, 3, 4)
print(set(range(5)))           # {0, 1, 2, 3, 4}

# String → list of characters
print(list("hello"))           # ['h', 'e', 'l', 'l', 'o']
print(tuple("hello"))          # ('h', 'e', 'l', 'l', 'o')
print(set("hello"))            # {'h', 'e', 'l', 'o'}  (unique)

# List ↔ tuple
lst = [1, 2, 3]
t   = tuple(lst)               # (1, 2, 3)
lst2 = list(t)                 # [1, 2, 3]

# List → set (removes duplicates)
lst = [1, 2, 2, 3, 3, 3]
s = set(lst)                   # {1, 2, 3}
lst3 = sorted(list(s))         # [1, 2, 3]

dict() — Building Dictionaries

# From list of 2-tuples
pairs = [("a", 1), ("b", 2), ("c", 3)]
d = dict(pairs)
print(d)   # {'a': 1, 'b': 2, 'c': 3}

# From list of 2-lists
d2 = dict([["x", 10], ["y", 20]])
print(d2)  # {'x': 10, 'y': 20}

# From set of tuples (order undefined!)
d3 = dict({(1, "one"), (2, "two")})
print(d3)  # {1: 'one', 2: 'two'}

# Using keyword arguments
d4 = dict(alpha=1, beta=2, gamma=3)
print(d4)

# From enumerate
words = ["zero", "one", "two"]
d5 = dict(enumerate(words))
print(d5)   # {0: 'zero', 1: 'one', 2: 'two'}

# From zip
d6 = dict(zip("abc", [1, 2, 3]))
print(d6)   # {'a': 1, 'b': 2, 'c': 3}

dict iterables → other types

d = {"name": "Alice", "age": 30, "city": "NYC"}

# Keys
key_list  = list(d.keys())     # ['name', 'age', 'city']
key_tuple = tuple(d.keys())    # ('name', 'age', 'city')
key_set   = set(d.keys())      # {'name', 'age', 'city'}

# Values
val_list  = list(d.values())   # ['Alice', 30, 'NYC']
val_tuple = tuple(d.values())  # ('Alice', 30, 'NYC')

# Items (key, value pairs)
item_list  = list(d.items())   # [('name', 'Alice'), ('age', 30), ('city', 'NYC')]
item_tuple = tuple(d.items())  # (('name', 'Alice'), ...)

sorted() with key Function

# Sort list of tuples by second element
data = [("Alice", 85), ("Bob", 92), ("Charlie", 78)]
by_score = sorted(data, key=lambda x: x[1])
print(by_score)   # [('Charlie', 78), ('Alice', 85), ('Bob', 92)]

# Sort dict by value
d = {"banana": 3, "apple": 1, "cherry": 2}
by_value = sorted(d.items(), key=lambda x: x[1])
print(dict(by_value))   # {'apple': 1, 'cherry': 2, 'banana': 3}

# Sort by multiple keys
students = [("Alice", 85, "B"), ("Bob", 92, "A"), ("Alice", 78, "C")]
by_name_then_score = sorted(students, key=lambda x: (x[0], x[1]))
print(by_name_then_score)

map() and filter() — Functional Transforms

map() — Apply function to every item

nums = [1, 2, 3, 4, 5]

# Old way
squares = []
for n in nums:
    squares.append(n**2)

# With map() — returns iterator
squares = list(map(lambda n: n**2, nums))
print(squares)   # [1, 4, 9, 16, 25]

# Convert strings to ints
strs = ["10", "20", "30"]
ints = list(map(int, strs))
print(ints)   # [10, 20, 30]

# Multiple iterables
a = [1, 2, 3]
b = [10, 20, 30]
sums = list(map(lambda x, y: x + y, a, b))
print(sums)   # [11, 22, 33]

filter() — Keep only matching items

nums = [1, -2, 3, -4, 5, -6]

positives = list(filter(lambda n: n > 0, nums))
print(positives)   # [1, 3, 5]

# Filter None/falsy values
mixed = [1, None, 2, 0, 3, "", 4, False]
truthy = list(filter(None, mixed))   # filter(None, ...) removes falsy
print(truthy)   # [1, 2, 3, 4]

dict.fromkeys() — Create dict with default values

keys = ["name", "age", "email"]

# All values set to None
template = dict.fromkeys(keys)
print(template)   # {'name': None, 'age': None, 'email': None}

# All values set to a default
init = dict.fromkeys(keys, "unknown")
print(init)   # {'name': 'unknown', 'age': 'unknown', 'email': 'unknown'}

# Remove duplicates from list, preserving order (Python 3.7+)
lst = [3, 1, 2, 1, 3, 4]
unique = list(dict.fromkeys(lst))
print(unique)   # [3, 1, 2, 4]

Practice Problems

# 1. Create a numbered menu
menu_items = ["Pizza", "Burger", "Sushi", "Tacos"]
for i, item in enumerate(menu_items, 1):
    print(f"  {i}. {item}")

# 2. Combine parallel lists into records
names  = ["Alice", "Bob", "Charlie"]
ages   = [30, 25, 35]
cities = ["NYC", "LA", "Chicago"]

records = [{"name": n, "age": a, "city": c}
           for n, a, c in zip(names, ages, cities)]
for r in records:
    print(r)

# 3. Word count with enumerate for indexing
words = "the quick brown fox jumps over the lazy dog".split()
word_index = {word: i for i, word in enumerate(words)}
print(word_index.get("fox"))   # 3

# 4. Transpose matrix
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
transposed = [list(row) for row in zip(*matrix)]
print(transposed)
# [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

# 5. Progress bar with enumerate
import time
tasks = ["Loading", "Processing", "Saving", "Done"]
for i, task in enumerate(tasks, 1):
    print(f"[{i}/{len(tasks)}] {task}...")
    # time.sleep(0.5)

Exercises: 05-07: Exercises — zip(), enumerate(), and Conversions


⬅️ Previous: 05-06: Data Structures Comparison — str, list, tuple, set, dict ➡️ Next: 06-01: Comprehensions — list, set, dict