今日、12月21日は「12/21」とも書く。
これは回文である。
そこで、回文が作りやすくなる?エディタを作ってみた。
仕様
- 文字列の入力を受け取る
- 入力された文字列と、それを反転させた文字列を繋げて表示する
文字列を文字に分割する
JavaScript では、文字列を UTF-16 のコードポイントの列として扱う。
そのため、何も考えずに文字列を反転させようとすると、サロゲートペアを破壊して変な表示になってしまうことがある。
さらに、サロゲートペアを考慮しても、絵文字などの合成文字を破壊してしまう可能性が残る。
確か、文字列を見た目通りの文字に分割するライブラリがあっただろうと思い、AIに聞いてみた。
Perplexity AI: JavaScript で、文字列をUnicodeの合成とかを考慮して人間にとって自然な文字単位に分割するライブラリあったよね。なんてやつだっけ? (魚拓)
すると、なんと今は主要ブラウザの標準機能でできることがわかった。(Firefox では今年 (2024年) 4月かららしい!)
具体的には、Intl.Segmenter を用いる。
まず、コンストラクターで Intl.Segmenter
のオブジェクトを生成する。
引数なしで呼び出すと、文字列を文字単位で分割する設定になる。
次に、このオブジェクトの segment()
メソッドを用いることで、文字列を文字単位に分割できる。
このメソッドは、分割した文字に加えてその他の情報も格納されたオブジェクトの列 (反復可能オブジェクト) Intl.Segments
を返す。
これを Array.from
メソッドで配列に変換し、map()
メソッドでオブジェクトから segment
メンバを取り出すことで、文字の配列が得られる。
このオブジェクトを用いて、
JavaScript Text Character Splitting (1文字毎に分解) #文字列 - Qiita
に乗っているサンプルの文字列を文字に分割してみる。
const inputString = 'A01赤-葛󠄀城市😄👨👩👧👦!';
const segmenter = new Intl.Segmenter();
const chars = Array.from(segmenter.segment(inputString)).map((s) => s.segment);
console.log(JSON.stringify(chars));
これを実行すると、
["A","0","1","赤","-","葛󠄀","城","市","😄","👨👩👧👦","!"]
と出力され、複数の文字を合成した絵文字を含む文字列を正しく文字に分割できていそうであることがわかる。
配列を逆順にする
concat()
で配列のコピーを取り、reverse()
を用いることで、配列を逆順にできる。
最近のブラウザでは toReversed()
メソッドも使えるようだが、この方法のようがより幅広い環境で動くだろう。
成果物
プロジェクトページ:mikecat/kaibun_editor: Show entered string plus reversed one.
おわりに
これを用いることで回文の検証はしやすくなるかもしれないが、回文を思いつくのは難しいかもな…