「👍」の文字数を数えたら、10言語で 1・2・4 の3通りに割れた ― その書き方、本当に通る?⑩

C#
B!

文字列の長さを数える関数は、どの言語にもあります。ところが「👍」を渡すと、答えは 1・2・4 の3通りに割れました。10言語中7言語が、1 と答えませんでした。

何をしたか

CODE Polyglot の入門 第4回 は、文字列の文字数とバイト数(UTF-8)を出すプログラムです。この回では、Unicode の文字(コードポイント)の数を「文字数」の正解にしています。

JavaScript ならこう書きます。

console.log(`文字数: ${s.length}`);

各言語のいちばん普通の書き方で、毎朝の検証と同じ Linux の環境で動かした結果です。

入力正解Python len・Ruby lengthSwift countJavaScript length・Java length()・Kotlin length・C# LengthGo len・PHP strlen・Rust len()
abc33333
あいう33339
𠮷野家333410
👍11124
家族👨‍👩‍👧7731024

6件のうち正解だった数は、Python・Ruby が6件中6件、Swift が6件中5件、JavaScript・Java・Kotlin・C# が6件中3件、Go・PHP・Rust が6件中1件でした。

数えているものが4通りある

  • バイト(Go・PHP・Rust): UTF-8 に直したときの長さ。ひらがなは1文字3バイト、絵文字は4バイト。英字だけのテストでは正しく見える
  • UTF-16 の単位(JavaScript・Java・Kotlin・C#): ふだん使う文字は1つ。ただし「𠮷」や絵文字は2つと数える。日本語のテストでも、ひらがなと常用漢字だけなら気づけない
  • Unicode の文字(Python・Ruby): 「👍」も「𠮷」も1つ。家族の絵文字は、人の絵文字3つと、つなぐ記号2つの合計5つと数える
  • 見た目の1文字(Swift): 家族の絵文字も1つ。だから 家族👨‍👩‍👧 は3になる

Swift の答えは、この回の正解とは違いますが、画面に見える文字の数としては自然です。どれが正しいかは、何のために数えるのかで決まります。データベースの列の長さならバイトか文字、入力欄の「あと何文字」なら見た目の1文字が近いでしょう。

どう直したか

この回の正解(Unicode の文字の数)に合わせるには、次のように書きます。

// Go の len はバイト数を数える。文字(rune)の数は utf8.RuneCountInString で数える
fmt.Printf("文字数: %d\n", utf8.RuneCountInString(s))
// length は UTF-16 の単位を数える(「𠮷」は 2)。[...s] で1文字ずつに分けてから数える
console.log(`文字数: ${[...s].length}`);
// length() は UTF-16 の単位を数えるので「𠮷」や絵文字が 2 になる。codePointCount で Unicode の文字を数える
System.out.println("文字数: " + s.codePointCount(0, s.length()));
// Length は UTF-16 の単位を数えるので「𠮷」や絵文字が 2 になる。EnumerateRunes で Unicode の文字を数える
Console.WriteLine($"文字数: {s.EnumerateRunes().Count()}");
// len() は UTF-8 のバイト数を返す。Unicode の文字の数は chars().count() で数える
println!("文字数: {}", s.chars().count());
// count は見た目の1文字(家族の絵文字は 1)を数える。unicodeScalars.count で Unicode の文字を数える
print("文字数: \(s.unicodeScalars.count)")

直した版は、10言語とも6件中6件が正解になりました。

まとめ

  • 「👍」の文字数は、10言語で 1・2・4 に割れた。10言語中7言語が 1 と答えなかった
  • 長さの関数が数えるものは、バイト・UTF-16 の単位・Unicode の文字・見た目の1文字の4通り
  • 英字とひらがなだけのテストでは、JavaScript・Java・Kotlin・C#・Swift の間違いに気づけない。テストには 𠮷 と絵文字を入れる
  • 「文字数」は、何のために数えるのかを先に決める
  • 10言語の全プログラムは 入門 第4回 にあります
B!
← 一覧へ戻る