JavaScriptで文字列を比較・処理する前に!String.prototype.normalize()の使い方と注意点
Unicode 正規化 には、いくつかの種類があり、それぞれ異なる処理を行います。String.prototype.normalize()
メソッドでは、以下の 4 つの正規化形式を指定することができます。
- NFKD (Normalization Form Compatibility Decomposition)
NFD と同様に結合記号を分解し、さらに互換性のある記号に変換します。 - NFD (Normalization Form Canonical Decomposition)
すべての結合記号を分解し、基底文字と分離された記号に置き換えます。 - NFKC (Normalization Form Compatibility Composition)
NFC と同様に合成文字を分解し、さらに互換性のある記号に変換します。 - NFC (Normalization Form Canonical Composition)
すべての合成文字を分解し、基底文字と結合記号に置き換えます。
例:
const text1 = "film"; // ラテン文字小文字 f と i の結合文字
const text2 = "fi\x{332}"; // ラテン文字小文字 f と i の後に結合記号を付けた文字
console.log(text1 === text2); // false
console.log(text1.normalize('NFKC') === text2.normalize('NFKC')); // true
上記の例では、text1
と text2
は見た目こそ同じですが、実際には異なる文字表現になっています。しかし、normalize()
メソッドを使って NFKC
形式に正規化すると、両方の文字列は同じ表現になり、===
演算子で比較しても true
となります。
String.prototype.normalize()
メソッドの利点
- 国際化対応を容易にする
- データベースや検索エンジンでの文字列の一貫性を保つ
- 文字列の比較を容易にする
String.prototype.normalize()
メソッドの使用例
- 異なる言語の文字列を比較する
- 検索クエリの正規化を行い、検索結果の精度を向上させる
- ユーザー入力された文字列を正規化して、データベースに保存する
- すべての環境で
String.prototype.normalize()
メソッドがサポートされているわけではありません。 - 正規化形式によっては、元の文字列と見た目や意味が異なる場合があります。
String.prototype.normalize()
メソッドは、処理に時間がかかる場合があります。
const text1 = "film"; // ラテン文字小文字 f と i の結合文字
const text2 = "fi\x{332}"; // ラテン文字小文字 f と i の後に結合記号を付けた文字
console.log(text1 === text2); // false
console.log(text1.normalize('NFKC') === text2.normalize('NFKC')); // true
データベースへの保存
以下のコードは、ユーザー入力された文字列を NFKC
形式に正規化して、データベースに保存する例です。
const userInput = prompt("名前を入力してください: ");
const normalizedName = userInput.normalize('NFKC');
// データベースに normalizedName を保存
検索クエリの正規化
以下のコードは、検索クエリの NFKD
形式に正規化を行い、検索結果の精度を向上させる例です。
const query = prompt("検索クエリを入力してください: ");
const normalizedQuery = query.normalize('NFKD');
// normalizedQuery を使って検索を実行
const germanText = "Hällo"; // ドイツ語の挨拶
const greekText = "Γεια σας"; // ギリシャ語の挨拶
console.log(germanText === greekText); // false
console.log(germanText.normalize('NFD') === greekText.normalize('NFD')); // true
正規表現
正規表現を使用して、文字列から不要な記号や結合文字を削除することができます。ただし、正規表現は複雑になる場合があり、String.prototype.normalize()
メソッドよりも処理速度が遅い場合があります。
const text = "film"; // ラテン文字小文字 f と i の結合文字
const normalizedText = text.replace(/[\u{1D179}]/g, "fi");
console.log(normalizedText); // fi
ライブラリ
Unicode
や unf
などのライブラリを使用して、Unicode 文字列の正規化を行うことができます。これらのライブラリは、String.prototype.normalize()
メソッドよりも高速で機能が豊富な場合があります。
const { normalize } = require("unicode-normalization");
const text = "film"; // ラテン文字小文字 f と i の結合文字
const normalizedText = normalize(text, "NFKC");
console.log(normalizedText); // fi
手動変換
簡単な文字列の場合は、手動で変換することもできます。ただし、これは трудоемкий でエラーが発生しやすい方法です。
const text = "film"; // ラテン文字小文字 f と i の結合文字
const normalizedText = "f" + "\x{332}";
console.log(normalizedText); // fi
- 非常に簡単な文字列の場合
手動変換 - より多くの制御が必要な場合
正規表現 - 高速な処理が必要な場合
ライブラリ (例:unicode-normalization
,unf
) - シンプルで使いやすい方法
String.prototype.normalize()
メソッド