読みがなを正しい50音順(辞書順)にソートする

読みがなを持つデータを、辞書のような順序に並べ替えたいとする。

ところが辞書の配列は意外と複雑だ。Wikipedia の索引の配列として次の規則が提示されている。

  1. 読みの五十音順とする。
  2. 清音・濁音・半濁音は、この順に並べる。
  3. 促音「っ」、拗音「ゃ」「ゅ」「ょ」はそれぞれ「つ」「や」「ゆ」「よ」の後に並べる。
  4. 小文字「ァ」「ィ」「ゥ」「ェ」「ォ」はそれぞれ「あ」「い」「う」「え」「お」の後に並べる。
  5. 長音符「ー」は直前の母音を表すものとし、それぞれ仮名の後に並べる。
    例: 「コーヒー」は「こおひい」と見なす。
  6. ひらがなとカタカナは、この順に並べる。
プロジェクト‐ノート:索引/配列順 - Wikipedia

成果物

PHP で Composer から使用できるライブラリを作成した。次のコマンドでプロジェクトに追加できる。

composer require sharapeco/kana-order

次のように KanaOrder::get メソッドを使用して既存のデータに並べ替え用のデータを付加し、 usort 関数を使って並べ替えを行うことができる。

<?php
require_once 'vendor/autoload.php';
use sharapeco\KanaOrder\KanaOrder;

$items = [
	['name' => '進め', 'kana' => 'すすめ'],
	['name' => 'スズメ', 'kana' => 'スズメ'],
	['name' => '鈴なり', 'kana' => 'すずなり'],
	['name' => 'ススキ', 'kana' => 'ススキ'],
	['name' => 'すり抜け', 'kana' => 'すりぬけ'],
];

$items = array_map(function($item) {
	$item['sort_key'] = KanaOrder::get($item['kana']);
	return $item;
}, $items);

usort($items , function($x, $y) {
	return strcmp($x['sort_key'], $y['sort_key']);
});

リポジトリおよび Packagist のページはこちら。

別の方法:ICU ライブラリを使用する

ICU は International Components for Unicode の略で、ロケール関連のさまざまな操作ができるライブラリだ。PHP からは intl 拡張モジュールとして使用できる。

PHP ではその中にある Collator クラスでロケール固有の並び順を考慮した文字列の比較、ソートができる。

単純に項目を並べ替える場合は sort メソッドが使用できる。

<?php
$items = ['すすめ', 'すずめ', 'すずなり', 'すすき', 'すりぬけ'];

$collator = new Collator('ja_JP');
$collator->sort($items);

また日本語では読みがな単体を並べ替える場合は少ないだろうから、 getSortKey メソッドを使い、次のように書ける。

<?php
$items = [
	['name' => '進め', 'kana' => 'すすめ'],
	['name' => 'スズメ', 'kana' => 'スズメ'],
	['name' => '鈴なり', 'kana' => 'すずなり'],
	['name' => 'ススキ', 'kana' => 'ススキ'],
	['name' => 'すり抜け', 'kana' => 'すりぬけ'],
];

$collator = new Collator('ja_JP');
$items = array_map(function($item) use ($collator) {
	$item['sort_key'] = $collator->getSortKey($item['kana']);
	return $item;
}, $items);

usort($items , function($x, $y) {
	return strcmp($x['sort_key'], $y['sort_key']);
});

ところがこのライブラリを使った方法では一般的に使われている規則と違い、次のような差異がある。

  • ひらがなよりカタカナが先に来る
  • 促音、拗音、小文字、長音符が通常のかなより先に来る

そのため新しくライブラリを作成した。

アイディア

ひらがなとカタカナに関するソートキーを得る方法として、各かなを「清音 + 付加情報」として表す方法を考えた。はじめに清音でソートし、清音が等しい場合は付加情報を付加した文字列を比較する。ラテン文字や算用数字、記号については考慮していない。

  1. ひらがな清音の場合は付加情報としてスペースを足す(すすめ→すすめ SP SP SP; 見えないので SP と表記)
  2. ひらがな濁音は " (すずめ→すすめ SP " SP)
  3. ひらがな半濁音および拗促音は $ (ぴゅっ→ひゆつ$$$)
  4. カタカナ清音は ! (ススメ→すすめ!!!)
  5. カタカナ濁音は # (スズメ→すすめ!#!)
  6. カタカナ半濁音および拗促音は % (ピュッ→ひゆつ%%%)

このとき SP ! " # $ % はコード順になっていることに留意。