BE AWESOME
Settings
Web Tools
📅 August 3, 2026 · ⏱️ 4 min read

List Comparator: Three Buckets, Not One Confusing Diff

Only in A, only in B, or in both — and how building this right after Duplicate Finder made the performance lesson land twice as fast.

This post is about List Comparator: Three Buckets, Not One Confusing Diff
Try the List Comparator →

Two pasted lists in, three answers out: what's only in A, what's only in B, and what's in both. It's a small tool built to answer one specific, recurring comparison question that comes up constantly with two exports — a before-and-after inventory, two versions of a mailing list — without manually cross-referencing every line between two windows by hand.

Set operations are the easy part; presenting them clearly is the actual job

Computing which items are unique to each list and which overlap is genuinely simple set math — build a set from each list, then intersect and difference them. That part took very little time. What took real care was presenting three separate result sections in a way that's scannable rather than just three undifferentiated dumps of text stacked on top of each other. Alphabetizing each section and clearly labeling which is which sounds obvious in hindsight, but the first version I built just concatenated results in whatever order the underlying set operations happened to produce, which was technically correct and genuinely hard to actually read.

Item counts up front changed how trustworthy this feels

The results start with a simple count of how many items were in list A and list B before showing any of the three comparison sections, and that small addition does real work building confidence in the result. Without visible input counts, there's no easy way to sanity-check that the tool actually processed the full list you pasted rather than silently truncating something or missing a line due to an unexpected line-ending character. Seeing "List A: 47 items, List B: 52 items" at the top lets you immediately confirm the tool saw what you expected it to see before you even look at the actual comparison.

Large lists needed the same performance discipline as Duplicate Finder

Comparing two large lists against each other has the same performance trap as finding duplicates within one list — a naive approach that checks every item in A against every item in B scales badly once both lists get long. Building both lists into proper lookup structures first, then checking membership against those structures rather than re-scanning the other list's full contents for every single item, keeps the comparison fast regardless of how large either list is. It's essentially the same underlying lesson from Duplicate Finder applied to a two-list problem instead of a one-list problem, and having just solved it once made solving it here noticeably faster.

Line-based comparison has real limits I didn't try to paper over

This compares whole lines as atomic units, which means it's genuinely the wrong tool for comparing, say, two CSV files where you actually care about matching on one specific column while ignoring differences in another. I thought about building column-aware comparison for structured data and decided it belonged in a different, more specialized tool rather than as an added mode bolted onto this one. Trying to handle both plain lists and structured tabular comparison in the same interface would make the common, simple case — comparing two lists of names or codes — more complicated to explain, in service of a more advanced use case that deserves its own dedicated design instead.

Case sensitivity here inherited the same lesson from Duplicate Finder

Whether "Apple" and "apple" should count as the same entry or different ones came up here in almost exactly the same shape it did while building Duplicate Finder a little earlier this same day, and I made the same call: expose it as a toggle rather than picking a silent default. It's a small piece of shared design thinking across two otherwise unrelated tools, and it's a good example of how building several small tools in the same stretch of time lets lessons from one immediately inform the next, rather than each tool starting from a completely blank set of assumptions about how text comparison should behave.

Copying the full report, not just one section

The copy button grabs the entire report — counts and all three sections together — rather than requiring three separate copies for three separate sections. That was a deliberate call based on how I actually imagined this getting used: pasted whole into an email or a ticket explaining exactly what changed between two versions of a list, not cherry-picked piece by piece. A tool that makes you copy its output in fragments is asking the person using it to do assembly work the tool itself should have just done for them.

Like Duplicate Finder, this is a small, specific tool rather than an ambitious one, and I think that's the right size for it. The two of them together cover a huge share of the "compare some text against other text" problem space people actually run into day to day, without either one trying to be a general-purpose diffing framework that solves every possible variation of the question at once.

Building two related small tools back to back in the same day also made it obvious how much faster the second one goes once the first has already forced a decision on a shared question like case sensitivity or performance at scale. That's a real, if unglamorous, benefit of shipping several small tools in the same sitting instead of spacing them out — the lessons don't have time to go stale before the next tool needs them, which is probably the strongest argument for building a batch of small, related tools together instead of spacing them weeks apart, even if it means several fairly quiet devlog posts land on the exact same date, each one small on its own but adding up to a genuinely productive day by the time all of them are done and each one is written up honestly on its own terms, with its own real decisions instead of a shared paragraph pretending they were all identical, which they weren't, even when two tools look similar enough from the outside to seem interchangeable at first glance, before you actually sit down and build both of them.

Hello!