Lambdaカクテル

京都在住Webエンジニアの日記です

Invite link for Scalaわいわいランド

松竹梅はsortしても松竹梅になる

物事の順位付けをするとき、松竹梅という雅な表現がよく使われる。自分もよく使う。

blog.3qe.us

コンピュータにとってもそうなのだろうか?そう考えた私は実際にソートしてみることにした。

% echo $LANG
ja_JP.UTF-8
% sort --version
sort (GNU coreutils) 9.3
Copyright (C) 2023 Free Software Foundation, Inc.
ライセンス GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

作者 Mike Haertel および Paul Eggert。
% echo -n "竹梅松" | sed -ne 's/./\0\n/gp' | sort
松
竹
梅

本当に松竹梅になった。

コードポイントやUTF-8バイト列を見る

ところで、本当にデータがこの通りになっているのだろうか。検証のために、エンコーディングを試すコードを書いてみた。

#!/usr/bin/env -S scala-cli shebang
//> using scala 3.3.0
//> using dep "commons-codec:commons-codec:1.16.0"

import org.apache.commons.codec.binary.Hex
import collection.JavaConverters.{*, given}

def byte2ubyte(b: Byte): Int = b & 0xff

for (s <- args) {
  val cp = s.codePoints
    .iterator()
    .asScala
    .map(i => BigInt(i.toInt))
    .map(_.toByteArray)
    .map(Hex.encodeHexString)
    .map(u => s"U+$u")
    .mkString(" ")

  val ss = s.getBytes().map(byte2ubyte).mkString(" ")
  val hex = Hex.encodeHexString(s.getBytes())
  println(s"$s -> $ss ($hex in hex array, $cp in Unicode codepoint)")
}

できた。

松竹梅のコードポイントとUTF-8表現を検査してみる。

% scala-cli show-utf8.scala.sc -- 松 竹 梅
Compiling project (Scala 3.3.0, JVM)
Warning: there was 1 deprecation warning; re-run with -deprecation for details
Compiled project (Scala 3.3.0, JVM)
松 -> 230 157 190 (e69dbe in hex array, U+677e in Unicode codepoint)
竹 -> 231 171 185 (e7abb9 in hex array, U+7af9 in Unicode codepoint)
梅 -> 230 162 133 (e6a285 in hex array, U+6885 in Unicode codepoint)

バイト列でもコードポイントでも、ぜんぜん竹のほうが大きいことがわかった。最下位バイトはちょうど降順になっているけれど、sortは普通は昇順で並べるので関係ないはず。

sortの実装

qiita.com

sortは、strcoll()を使って文字列を比較しているらしい。そしてそれはLC_COLLATE="ja_JP.UTF-8"を参照しているようだ。

ちなみにScalaでソートするとコードポイント順になる:

scala> "竹梅松".sorted
val res1: String = 松梅竹

自分のC読解力だとどこで差異が発生しているかわからなかった。暇な人はチャレンジしてみてください。

結論

  • 松竹梅はソートすると本当は松竹梅ではないが、sortすると松竹梅になる
★記事をRTしてもらえると喜びます
Webアプリケーション開発関連の記事を投稿しています.読者になってみませんか?