Write a function that reads a raw contact list, filters out invalid entries, sorts what's left, and writes a clean export.
export_valid_contacts(in_path, out_path)
in_path contains one "name,email" pair per line (no header, and some emails may be malformed).
./+/-, an @, a domain, a dot, and a final segment.out_path, one per line, formatted "name,email".Given in_path containing:
Zane,zane@example.com
Ada,not-an-email
Bob,bob@example.com
export_valid_contacts(in_path, out_path) returns 2, and writes to out_path:
Bob,bob@example.com
Zane,zane@example.com
(Ada's malformed email excludes her from the output entirely — she doesn't appear at all, not even with a blank email.)
import re
EMAIL_PATTERN = r"[\w.+-]+@[\w-]+\.[\w.-]+"
def export_valid_contacts(in_path, out_path):
with open(in_path) as f:
lines = f.read().splitlines()
valid = []
for line in lines:
name, email = line.split(",")
if re.fullmatch(EMAIL_PATTERN, email):
valid.append((name, email))
valid.sort(key=lambda contact: contact[0])
with open(out_path, "w") as f:
f.write("\n".join(f"{name},{email}" for name, email in valid))
return len(valid)
Three stages, each reusing a tool from earlier in the course:
Filter (Regex): the exact validation pattern from Is Valid Email, reused wholesale rather than reinvented — a good instinct once you have a pattern that already works. Invalid lines are simply never added to valid; there's no error, no exception, no placeholder — they're excluded entirely, matching "Ada doesn't appear at all" in the example.
Sort (built-in): valid.sort(key=lambda contact: contact[0]) sorts the list of (name, email) tuples by name. key=lambda contact: contact[0] tells .sort() what to compare — here, the first element of each tuple — rather than trying to compare the tuples themselves (which would also sort by email as a tiebreaker, not what's wanted here, though it happens not to matter unless two contacts share a name).
This is deliberately done as two separate passes — filter completely, then sort the filtered result — rather than trying to filter and sort simultaneously. Combining unrelated pieces of logic into one pass usually isn't worth the complexity it adds; two clear, separate steps are easier to get right and easier to read back later.
Write and return (File I/O): same read-then-write shape as every file problem in this course, formatting each kept contact back into "name,email" and joining with \n. len(valid) gives the count to return, which happens to be exactly the number of lines written.
import re
EMAIL_PATTERN = r"[\w.+-]+@[\w-]+\.[\w.-]+"
def export_valid_contacts(in_path, out_path):
with open(in_path) as f:
lines = f.read().splitlines()
valid = []
for line in lines:
name, email = line.split(",")
if re.fullmatch(EMAIL_PATTERN, email):
valid.append((name, email))
valid.sort(key=lambda contact: contact[0])
with open(out_path, "w") as f:
f.write("\n".join(f"{name},{email}" for name, email in valid))
return len(valid)
Sign in to join the discussion.
No comments yet. Be the first to ask a question.
Press Run to execute your code, or Submit to test and complete this problem.