AI Skill Report Card

Computing Sequence Diffs

Computes and presents differences between sequences (text lines, strings, lists) using Python's difflib module. Use when comparing files, generating diffs, finding close string matches, computing similarity ratios, or building patch/merge-like output.

A87·Aug 14, 2026·Source: Web
15 / 15
Python
import difflib a = ["line1\n", "line2\n", "line3\n"] b = ["line1\n", "line2 modified\n", "line3\n"] diff = difflib.unified_diff(a, b, fromfile="a.txt", tofile="b.txt", lineterm="") print("\n".join(diff))

Output:

--- a.txt
+++ b.txt
@@ -1,3 +1,3 @@
 line1
-line2
+line2 modified
 line3
Recommendation
Add an example showing HtmlDiff or ndiff output to cover more of the decision table entries
14 / 15

Progress:

  • Identify the comparison need: line-by-line diff, similarity score, or closest-match lookup
  • Pick the right tool (see decision table below)
  • Prepare inputs as sequences (lists of lines/strings), not raw multi-line strings
  • Run the comparison
  • Format/present output (unified, context, or HTML)

Decision table:

NeedTool
Git-style unified diffdifflib.unified_diff(a, b)
Context diff (before/after blocks)difflib.context_diff(a, b)
Human-readable inline diff (ndiff style, +/-/?)difflib.ndiff(a, b)
Side-by-side HTML diffdifflib.HtmlDiff().make_file(a, b)
Similarity ratio between two strings (0.0–1.0)difflib.SequenceMatcher(None, a, b).ratio()
Fuzzy match closest strings from a listdifflib.get_close_matches(word, possibilities)
Detailed opcodes (replace/insert/delete/equal ranges)SequenceMatcher.get_opcodes()

Steps:

  1. Read files with .readlines() (keepends=True) so diffs preserve line structure — don't use .split("\n") unless you strip newlines consistently.
  2. Choose the tool from the table.
  3. For SequenceMatcher, pass autojunk=False if comparing short/technical strings (default autojunk can skew results on repetitive text >200 chars).
  4. Join generator output with "\n".join(...) or iterate directly — these functions return generators/iterators, not lists.
Recommendation
Include a brief note on performance/alternatives (e.g., difflib vs. external libs like Levenshtein) for large-scale diffing
18 / 20

Example 1: Similarity ratio Input:

Python
difflib.SequenceMatcher(None, "python", "pytohn").ratio()

Output: 0.8333333333333334

Example 2: Closest match lookup Input:

Python
difflib.get_close_matches("appel", ["ape", "apple", "peach", "puppy"])

Output: ['apple', 'ape']

Example 3: Opcodes for custom diff rendering Input:

Python
s = difflib.SequenceMatcher(None, "qabxcd", "abycdf") s.get_opcodes()

Output:

Python
[('delete', 0, 1, 0, 0), ('equal', 1, 3, 0, 2), ('replace', 3, 4, 2, 3), ('equal', 4, 6, 3, 5), ('insert', 6, 6, 5, 6)]

Example 4: File diff (CLI-style) Input: two files old.py, new.py

Python
with open("old.py") as f1, open("new.py") as f2: diff = difflib.unified_diff(f1.readlines(), f2.readlines(), fromfile="old.py", tofile="new.py") print("".join(diff))

Output: standard unified diff text block with @@ hunk headers.

Recommendation
Show a bad/incorrect usage example (e.g., passing raw multiline string) alongside its fix for contrast
  • Use readlines() (keeps \n) for file diffs so unified_diff/context_diff output looks correct; use lineterm="" when lines already lack newlines.
  • Use get_close_matches(word, possibilities, n=3, cutoff=0.6) — tune n and cutoff for stricter/looser fuzzy matching.
  • For large files, prefer unified_diff over context_diff (more compact, standard for patches).
  • Cache a SequenceMatcher instance with set_seq2() when comparing one string against many candidates repeatedly — avoids reprocessing the second sequence each time.
  • Use Differ().compare() when you need inline +/-/? markers showing exact character-level changes within modified lines.
  • Don't pass raw strings with embedded \n directly to unified_diff/context_diff — split into a list of lines first.
  • Don't forget diffs are generators — printing the object directly shows a generator repr, not the diff.
  • Don't rely on default autojunk=True for short or highly repetitive strings; it can silently produce misleading ratios/matches.
  • ratio() is not symmetric-cost-free — it's O(n×m) in the worst case; avoid calling it in tight loops over large datasets without pre-filtering.
  • get_close_matches returns [] silently if nothing meets cutoff — always handle the empty-result case.
0
Grade AAI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
15/15
Workflow
14/15
Examples
18/20
Completeness
18/20
Format
15/15
Conciseness
14/15