Strings and Containers Comprehensive
In previous lessons, we covered lists, tuples, dictionaries, sets, and string methods. Now let's combine them — using the most common "combos" to solve real problems. These techniques are used daily in professional programming.
1. split() Working with Lists
split() breaks a string into a list — the first step in data processing:
# CSV data parsing
line = "Alice,25,Beijing,Engineer"
fields = line.split(",")
print(fields) # ['Alice', '25', 'Beijing', 'Engineer']
# Split by whitespace (default)
text = "hello world python"
words = text.split()
print(words) # ['hello', 'world', 'python']
# Limit the number of splits
data = "2026-06-23-15-30-00"
parts = data.split("-", 3)
print(parts) # ['2026', '06', '23', '15-30-00']
Example: Parsing a Config File (Difficulty ⭐⭐)
# Simulate parsing a config file
config_text = """
host=localhost
port=8080
debug=true
theme=dark
"""
# Split by line → split by equals sign → store in dictionary
config = {}
for line in config_text.strip().split("\n"):
if "=" in line:
key, value = line.split("=", 1)
config[key.strip()] = value.strip()
print(config)
# {'host': 'localhost', 'port': '8080', 'debug': 'true', 'theme': 'dark'}
# Read config
print(f"Current host: {config.get('host', 'localhost')}")
print(f"Current port: {config.get('port', '80')}")
Output:
{'host': 'localhost', 'port': '8080', 'debug': 'true', 'theme': 'dark'}
Current host: localhost
Current port: 8080
2. The Power of join()
join() is the reverse of split() — it merges a list into a string:
# Basic usage
words = ["Hello", "World", "Python"]
sentence = " ".join(words)
print(sentence) # Hello World Python
# Join with commas
csv = ",".join(["Alice", "25", "Beijing"])
print(csv) # Alice,25,Beijing
# Join with newlines
lines = "\n".join(["First line", "Second line", "Third line"])
print(lines)
Performance Advantages of join()
# ❌ Not recommended — string concatenation in a loop
result = ""
for i in range(1000):
result += str(i) + ","
# This creates 1000 temporary string objects (strings are immutable)
# ✅ Recommended — collect in a list + join()
parts = [str(i) for i in range(1000)]
result = ",".join(parts)
# One merge, much more efficient
Example: Formatting a Table (Difficulty ⭐⭐)
# Use join + list comprehension for formatted table output
headers = ["Name", "Age", "City"]
rows = [
["Alice", "25", "Beijing"],
["Bob", "30", "Shanghai"],
["Charlie", "22", "Guangzhou"],
]
# Header
print(" | ".join(headers))
print("-" * 25)
# Data rows
for row in rows:
print(" | ".join(row))
Output:
Name | Age | City
─────────────────────────
Alice | 25 | Beijing
Bob | 30 | Shanghai
Charlie | 22 | Guangzhou
3. sorted() with Strings and Dictionaries
sorted() works on any iterable, not just lists:
# Sort a string — alphabetical order
text = "python"
sorted_chars = sorted(text)
print(sorted_chars) # ['h', 'n', 'o', 'p', 't', 'y']
print("".join(sorted_chars)) # hnopty — recombined
# Sort a dictionary — sorts keys by default
d = {"banana": 3, "apple": 5, "cherry": 2}
sorted_keys = sorted(d)
print(sorted_keys) # ['apple', 'banana', 'cherry']
# Sort by value
sorted_by_value = sorted(d.items(), key=lambda x: x[1])
print(sorted_by_value) # [('cherry', 2), ('banana', 3), ('apple', 5)]
# Sort a set
s = {3, 1, 4, 1, 5, 9}
sorted_set = sorted(s)
print(sorted_set) # [1, 3, 4, 5, 9]
Example: Custom Sort Rule (Difficulty ⭐⭐)
# Sort filenames by numeric part
files = ["file_10.txt", "file_2.txt", "file_1.txt", "file_20.txt"]
# Regular sort — string sort, "10" comes before "2" (since '1' < '2')
print(sorted(files))
# ['file_1.txt', 'file_10.txt', 'file_2.txt', 'file_20.txt']
# Sort by numeric part — extract number, convert to int, then sort
def extract_number(filename):
num_str = filename.split("_")[1].split(".")[0]
return int(num_str)
sorted_files = sorted(files, key=extract_number)
print(sorted_files)
# ['file_1.txt', 'file_2.txt', 'file_10.txt', 'file_20.txt']
4. enumerate() and zip()
These two built-in functions are extremely common in daily work.
enumerate() — Get Index While Iterating
fruits = ["apple", "banana", "orange"]
# Without enumerate — clunky
for i in range(len(fruits)):
print(f"{i + 1}. {fruits[i]}")
# With enumerate — elegant
for i, fruit in enumerate(fruits, 1): # start=1 for 1-based counting
print(f"{i}. {fruit}")
zip() — Parallel Iteration Over Multiple Lists
names = ["Alice", "Bob", "Charlie"]
scores = [85, 92, 78]
cities = ["Beijing", "Shanghai", "Guangzhou"]
# Iterate over three lists simultaneously
for name, score, city in zip(names, scores, cities):
print(f"{name}: {score} points, from {city}")
Output:
Alice: 85 points, from Beijing
Bob: 92 points, from Shanghai
Charlie: 78 points, from Guangzhou
Example: Student Score Report (Difficulty ⭐⭐⭐)
# Generate a full report card using enumerate + zip
students = ["Alice", "Bob", "Charlie", "Diana"]
chinese = [85, 92, 78, 88]
math = [90, 85, 95, 80]
english = [78, 95, 82, 90]
print("=== Student Score Report ===")
print(f"{'Rank':<4}{'Name':<8}{'Chinese':<8}{'Math':<8}{'English':<8}{'Average':<8}")
# Calculate averages
averages = [(c + m + e) / 3 for c, m, e in zip(chinese, math, english)]
# Sort by average descending
data = list(zip(students, chinese, math, english, averages))
data.sort(key=lambda x: x[4], reverse=True)
# Output
for rank, (name, c, m, e, avg) in enumerate(data, 1):
print(f"{rank:<4}{name:<8}{c:<8}{m:<8}{e:<8}{avg:<8.1f}")
5. Comprehensive Data Processing Case
Let's apply everything we've learned to a real-world scenario:
Case: Log Analysis (Difficulty ⭐⭐⭐)
# Simulated server log
log_data = """
2026-06-20 10:23:45 INFO User 1001 logged in
2026-06-20 10:25:12 ERROR Database connection timeout
2026-06-20 10:26:30 INFO User 1002 logged in
2026-06-20 10:27:45 WARN Disk usage 85%
2026-06-20 10:28:10 ERROR User 1001 request timeout
2026-06-20 10:29:00 INFO User 1001 logged out
"""
# 1. Split by lines
lines = log_data.strip().split("\n")
# 2. Parse each log entry
parsed = []
for line in lines:
parts = line.split()
timestamp = f"{parts[0]} {parts[1]}"
level = parts[2]
message = " ".join(parts[3:])
parsed.append({"time": timestamp, "level": level, "msg": message})
# 3. Count by level
level_count = {}
for entry in parsed:
level = entry["level"]
level_count[level] = level_count.get(level, 0) + 1
# 4. Output sorted by level
print("=== Log Statistics ===")
for level, count in sorted(level_count.items()):
print(f"{level}: {count} entries")
# 5. Filter all ERRORs
print("\n=== Error Details ===")
errors = [e for e in parsed if e["level"] == "ERROR"]
for e in errors:
print(f"[{e['time']}] {e['msg']}")
Output:
=== Log Statistics ===
ERROR: 2 entries
INFO: 3 entries
WARN: 1 entry
=== Error Details ===
[2026-06-20 10:25:12] Database connection timeout
[2026-06-20 10:28:10] User 1001 request timeout
Common Use Cases
- Config parsing:
split()by delimiter → store in dictionary. - Data export: List comprehension +
join()to format data as CSV or tables. - Log analysis: Split by line → parse fields → store in dict →
sorted()and comprehensions for stats. - Multi-table joins:
zip()to parallel-iterate multiple data lists into complete records. - Ranking:
enumerate(sorted(...))to generate numbered sorted results.
❓ FAQ
split() and split(" ")?split() without arguments splits on any whitespace (spaces, newlines, tabs) and automatically removes empty strings. split(" ") only splits on single spaces; consecutive spaces produce empty strings. In most cases, split() without arguments is the better choice.
⚠️ Q: Does join() require all elements in the list to be strings? A: Yes. ",".join([1, 2, 3]) will error. Convert numbers to strings first: ",".join(str(x) for x in [1, 2, 3]) or use str() in a list comprehension.
Q: What happens when zip() processes lists of different lengths? A: zip() stops at the shortest list. If one of three lists has only 2 elements, zip() only produces 2 pairs. To pad with None for the longest list, use itertools.zip_longest().📖 Summary
split()breaks a string into a list; without arguments, splits on whitespace and auto-removes emptiesjoin()merges a list into a string; the preferred way to concatenate strings (more efficient than+=)sorted()works on any iterable — strings, dicts, setsenumerate()gets the index during iteration;startparameter specifies the starting valuezip()parallel-iterates over multiple lists; great for merging related data- Combining these tools enables efficient real-world data processing
📝 Exercises
-
Basic (Difficulty ⭐): Given
s = "apple,banana,orange,grape", usesplit()to break it into a list, then usejoin()to output"apple | banana | orange | grape". -
Intermediate (Difficulty ⭐⭐): Given two lists
students = ["Alice", "Bob", "Charlie"]andscores = [85, 92, 78], usezip()andenumerate()to output a ranked report:TEXT#1: Bob — 92 points #2: Alice — 85 points #3: Charlie — 78 points -
Challenge (Difficulty ⭐⭐⭐): Write a "Simple CSV Generator." Given a list of lists
data = [["Name", "Age", "City"], ["Alice", 25, "Beijing"], ["Bob", 30, "Shanghai"]], output it as a CSV string (comma-separated rows). Hint: Usestr()in list comprehension for numbers,",".join()for each row,"\n".join()for all rows.



