要約:"重複"行は常に同一のバイト列とは限りません — 末尾のスペース、大文字小文字の違い、Unicode正規化の違いが本当の重複を隠したり、偽の重複を作り出したりすることがあります。比較の仕組みを理解することで、必要な行を誤って削除するのではなく、正確なクリーンアップができるようになります。このガイドはRemove Duplicate Lines、Text Difference、Word Frequency、Remove Extra Spacesと組み合わせて使ってください。

CharCountのDuplicate Finderは、リスト、ログ、CSVエクスポート、キーワードリストから重複行を削除します。難しいのは削除そのものではなく — 何かを削除する前に何を"同じ行"とみなすかを決めることです。

背景:JavaScript SetのMDNリファレンスはほとんどの重複排除ツールが内部で使用するデータ構造を説明し、String.normalize()のMDNガイドはUnicode正規化を扱い、Unicodeテキストセグメンテーションレポート(UAX #29)はテキストが意味のある単位にどう分割されるかを定義しています。

テキスト内の重複行を素早く見つけて削除する方法

重複検出の実際の仕組み

内部では、重複行ツールは各行を巡回し、既に見たことがあるかどうかをチェックします — 通常はSetを使い、一意な値を保存し、定数時間で完全な重複を判定します。これは高速ですが、"完全"という言葉がその一文で多くの意味を担っています。Setは文字列のUTF-16コード単位の並びを比較するので、"りんご"と"りんご "(末尾にスペースあり)は異なるエントリになります。

これが、CSVエクスポートやスクレイピングしたキーワードリストに対する単純な重複排除がしばしば"失敗する"理由です — ツールが壊れているのではなく、目に見えないスペースや気づかなかった大文字小文字の違いも含めて、与えられたものを正確に比較しているだけなのです。

順序の保持 vs ソートしてから重複排除

一般的な戦略は2つあります。順序を保持する重複排除は各行の最初の出現とその元の位置を維持します — ログ、チャットのエクスポート、あるいは順序が意味を持つあらゆる場合に適した選択です。ソートしてから重複排除する方法(古典的なUnixパイプラインsort | uniqのような)はまずすべてをアルファベット順に並べ替え、巨大なファイルでは高速ですが元の順序を破壊します — キーワードリストには適していますが、変更履歴には不適切です。

"何が先に来たか"が重要な場合は常に順序保持を選び、リストの順序がそもそも任意だった場合にのみソートしてから重複排除を選んでください。

正規化が重複排除の結果を変える場合

Unicodeでは、同じ見た目の文字が異なるバイト列として存在できます — アクセント付き文字は単一の合成コードポイント(NFC)か、基底文字と別の結合アクセント記号(NFD)のいずれかになり得ます。画面上では同一に見える2行が、正確一致の重複排除で失敗することがあります。一方がMacエクスポート、もう一方がWindowsエクスポートから来ていて、異なる正規化形式になっている場合です。

String.normalize('NFC')は比較の前に両方の形式を同じ表現に統合します。これが、優れた重複ツールがまずテキストを正規化する理由です — さもなければ、視覚的には同一だがバイト単位では同一でない重複を気づかないまま見落としてしまいます。

より安全なクリーンアップの流れ

  • まず決める:このリストで行の順序は重要か? これが戦略を決めます。
  • リストが大文字小文字を区別しないことを意図している場合にのみ(キーワードリストではよくあり、パスワードリストでは決してない)、末尾のスペースを削除し大文字小文字を正規化する。
  • 重複排除を実行し、削除された行のサンプルを確認して本当に重複だったか確かめる。
  • クリーンな版を検証するまで元のファイルを保持する。

曖昧なケースについては、削除前後をText Differenceにかけて何が削除されたかを正確に確認し、Word Frequencyで正当な繰り返し用語がノイズとして扱われていないか確認してください。