DEV Community

toolzip
toolzip

Posted on Originally published at toolzip.app

Text Deduplication Algorithms — From O(n ) to O(n)

Text Deduplication Algorithms — From O(n²) to O(n)

Removing duplicate lines sounds trivial. The naive approach works for small inputs but breaks down at scale. Here's how to do it efficiently.

The Naive Approach: O(n²)

function dedupNaive(lines) {
  const result = [];
  for (const line of lines) {
    if (!result.includes(line)) {
      result.push(line);
    }
  }
  return result;
}
Enter fullscreen mode Exit fullscreen mode

Array.includes() is O(n), so this is O(n²) overall. For 10,000 lines, that's 50 million comparisons.

Using a Set: O(n)

function dedupWithSet(lines) {
  return [...new Set(lines)];
}
Enter fullscreen mode Exit fullscreen mode

Set uses a hash table internally, giving O(1) average lookup. This is 100x faster for large inputs.

Case-Insensitive Deduplication

function dedupCaseInsensitive(lines) {
  const seen = new Set();
  return lines.filter(line => {
    const key = line.toLowerCase();
    if (seen.has(key)) return false;
    seen.add(key);
    return true;
  });
}
Enter fullscreen mode Exit fullscreen mode

Preserving Original Case While Deduplicating

Keep the first occurrence's original case:

function dedupPreserveCase(lines) {
  const seen = new Set();
  return lines.filter(line => {
    const key = line.trim().toLowerCase();
    if (seen.has(key)) return false;
    seen.add(key);
    return true;
  });
}
Enter fullscreen mode Exit fullscreen mode

Sort + Dedup

Sorting first, then deduplicating adjacent duplicates is O(n log n) but useful when you want sorted output:

function sortAndDedup(lines, caseInsensitive = false) {
  const sorted = [...lines].sort((a, b) => {
    const ca = caseInsensitive ? a.toLowerCase() : a;
    const cb = caseInsensitive ? b.toLowerCase() : b;
    return ca.localeCompare(cb);
  });

  return sorted.filter((line, i) => {
    if (i === 0) return true;
    const prev = caseInsensitive ? sorted[i-1].toLowerCase() : sorted[i-1];
    const curr = caseInsensitive ? line.toLowerCase() : line;
    return prev !== curr;
  });
}
Enter fullscreen mode Exit fullscreen mode

Performance Comparison

For 100,000 lines with 50% duplicates:

Method Time
Naive (includes) ~2,400ms
Set-based ~12ms
Sort + dedup ~45ms

The Set approach wins for pure deduplication. Sort + dedup wins when you also need sorted output.


Try it at toolzip.app/tools/text-dedup.

Top comments (0)