五十音の「辞書順」の処理


公開 (UL): 2021-02-23
更新 (UD): 2021-02-23
閲覧 (DL): 2021-03-01

この記事のもくじ

前の記事

2020-12-22
年月日から曜日を求める数式

最近の記事

2020-05-04
UTF-8 文字(列)と UNICODE の変換
2020-06-07
存在不明のパス名からディレクトリを構築する
2020-05-04
エスケープ文字変換/復元
2020-03-23
準プレーンテキスト形式
2019-12-06
プレーンテキスト文字化けのブラウザとサーバ対策
新着情報

新着情報 Recent docs.

Sorry, but almost these pages are only Japanese.
歴史が繰り返される理由 «How does the technology make fool generations.»
バレンタイン前夜(2021-02-13, 23:08)の最大震度6強地震で見えた「テクノロジーが愚かな世代を作る」仕組み。
詐欺メールを晒す! «A real phishing mail!»
サイト管理者の元に届いた「詐欺メール」を晒すとともに,その対処,防犯対策を紹介。
「モバイル Suica」2020年 12月~翌年3月で終了など機種まとめ «"Mobile Suica" will be stopped with these phones.»
12/22~来年3月までに「使えなくなる」などの機種テキスト一覧。
デジタル化なら「スタイル編集」すべき «Let's "Style-Editting" with word-processor application.»
ワープロで「書式設定」の代わりに「スタイル編集」することで使える様々な便利機能。
「差別意識」を世に広め続けるタテワリ行政 «"Tatewari" means hard to work over-ministries cooperation in Japan. I'm worried it makes racist mind.»
「タテワリ構造」が解消しないと「差別意識」も根絶できない話。

人気記事 Frequent view pages.

表計算で「令和」に対応する方法
How to adapt the Gengo era "Reiwa" on spreadsheet applicaiton.

古いアプリも OK。「表計算 令和」の検索結果上位御礼!
表計算ソフトで予定表を自動作成する超便利な方法 «How to make the schedule table automatically on spread-sheet.»
「毎月第○×曜日」的な法則は自動で作らせてラクしよう!
表計算ソフトに「個人情報保護機能」を仕込む方法 «Prevention to leak private-data with spread-​sheet macro function.»
「漏えい」のためのフェイルセーフ。「表計算 個人情報」の検索結果上位御礼!
Wary-Basher (ワリバッシャー)
DIY device that enables the handicapped to operate many things with a switch like push-button.

障害者の様々な操作をスイッチ操作で実現する器具。キットも発売中! 「作り方」PDF ダウンロード多数御礼!←地方教育委で人気。
NTT 東日本代理店の勧誘のあり方に対する疑問 «I feeled pretty doubt the solicitation of "Optical-fiber communication" from the agency of NTT-east corporation.»
「あえて」分かりにくい説明をする業者に儲けさせてはいないか?
貧乏人を殺す行政の構造 «Structurally, the administrators kill the poors in Japan.»
ヘタすると多摩川に流されるところだった台風 19 号

この記事に対する → 調布市の反応

おすすめ! Recommend

「事故防シート」について «Cared persons taking with "Jiko-​Bow-​Sheet" prevents from accidents.»
介護現場の負担軽減と事故防止のアイデア
キーボードの「キー」の詳しい使い方 «The detial of usage each key on keybord.»
各キーの機能詳細。機能別五十音順一覧。
和易ゐ記 (WAI-WIKI) «WAI-WIKI is light­weight markup language for Japanese, and generates HTML on this server on-​demand.»
当サイトで開発/使用中の日本語向けに特化した軽量マークアップ言語

ご支援 Support this site.

この活動をご支援いただける方はこちらへ
Could you support this site, see here (but Japanese).

 たとえば,以下のいくつかの言葉を「辞書順に」並べると,次のようになるだろう。

▼ 辞書順
   さつき	皐月
   さっき	殺気
   ざつき	座付
   ざっき	雑記
   さっきん	殺菌
   さつま	薩摩
   さんばし	桟橋

 ところが,これを perl に組み込まれている sort 関数でソートすると,以下の順になってしまう。

▼ sort 関数による並べ替え
   さっき	殺気
   さっきん	殺菌
   さつき	皐月
   さつま	薩摩
   さんばし	桟橋
   ざっき	雑記
   ざつき	座付

 何だかバラバラのようだが,コンピュータ的にはこれで合っている。おそらく,他の言語でも一般的な組み込みソート機能を使ったら,同じような結果になるのではないか。でも,なぜそうなるか,原因と回避策などを考えてみたい。

● 原因

 それは,文字コードにある。sort 関数は,原則として,単純に文字コード順に並べ替える機能だ。
 で,その比較がどうされているかというと,まず,なぜか小さい文字(「ぁぃぅぇぉっゃゅょ」など)に,そうでないものよりも小さい文字コードが割り当てられているため,文字コード順に並べると,それらが先に来てしまうという点。それと,コンピュータの辞書順比較では,前にある文字が優先的に評価される,という2点が原因。
 小さい字のほうが先に来るため,「さつき(皐月)」は,2文字目の「つ」が促音の「っ」より大きい文字コードのために,促音の「さっき(殺気)」や「さっきん(殺菌)」のほうが前に来てしまう。
 さらには,逆に濁音と半濁音は清音の字より大きい文字コードが割り当てられているため,最初の文字が「ざ」のものは全ての「さ」より後になる。そのため,濁音で始まる「ざっき(雑記)」は,清音で始まる「さんばし(桟橋)」よりも後に来てしまうことになる。

 実際の日本語の辞書はそうではないはず。まず「全て清音読み」した順に並べられて,その中で「小さい字」や「濁音,半濁音」が使われているものが後に来るようになる。だから,「さつき,さっき,ざつき,ざっき,さっきん」はこの順になる。「さつま」や「さんばし」などの後に来ることはないはずだ。

● 対策

 どうすればいいか。これは,まず全て「小文字ではない清音」で比較し,それで等しい場合に,小さい字か濁音,半濁音かを調べる……という「二段比較」が必要だと思う。
 表計算ソフトの「並び替え」で,「最優先する列」と「二番目に優先する列」……など,並び替えの基準にする値として複数の列を指定できるが,それと似たやり方が必要だろう。

 たとえば前述の「さつき,さっき,ざつき,ざっき」の場合は,まず優先する比較キーとして,全て小文字ではない清音の「さつき」で比較する。当然それでは全て同じになってしまうので,2番めの比較キーとして,小文字か濁音か……を示す別の値を求める必要が出てくる。たとえば,以下のような数値を割り当てる。

 前述の4つの言葉は,小文字でない清音で比較すると全て「さつき」となって同じだが,前述の法則で「2番めの比較キー」を作ると,以下のようになる。

 この右側の数を元に「辞書順に」並び替えれば,日本語の辞書に出て来る順番になる。
 ここで,この数のほうも「辞書順に」並び替える必要がある。というのは,たとえば「さっきん」は 0100 と4桁になるが,数値で比較すると,「ざつき」の 200 より小さくなってしまう。もっとも,優先キーの「さつき」と比較すると,文字数が多いからその時点で後になるはずだが,念のため。

 この方法で並び替えれば,文字コードに関係なく,小文字でない言葉を小文字よりも前に来るようにすることができる。

◆ Perl の場合

 sort に渡して処理可能な順序定義関数を kanaCmp とすると……。

▼ kanaCmp ひらがな辞書順の定義関数(抜粋)
   my	%sortBase = # ひらがな → ソート文字&キーペアハッシュ
	( ……,	'っ' => 'つ1', # 促音
		'つ' => 'つ0', # 清音
		'づ' => 'つ2', # 濁音
		……,
		'は' => 'は0', # 清音
		'ば' => 'は2', # 濁音
		'ぱ' => 'は3', # 半濁音
	…… ); # 実際はひらがな全てに定義
   my	%kanaSortDic;
   sub kanaSortKeyPair { my ( $k0, $k1 ) = ( '', '' );
	if( ! exists $kanaSortDic{ $_[0] } ){
	( "a".$_[0] )=~ /a/; # ↓ UTF-8 限定の処理
	  while( $' =~ /[\xC0-\xFD][\x80-\xBF]+/ ){
	  $k0 .= substr( $sortBase{ $& }, 0, 3 );
	  $k1 .= substr( $sortBase{ $& }, 3, 1 );
	  }
	$kanaSortDic{ $_[0] }= { k0 => $k0, k1 => $k1 };
	}
	return $kanaSortDic{ $_[0] };
   }
   sub kanaCmp {
    my ( $a, $b ) = ( kanaSortKeyPair( $_[0] ),
		kanaSortKeyPair( $_[1] ) );
	return ( $a ->{ k0 } cmp $b ->{ k0 } )||
			( $a ->{ k1 } cmp $b ->{ k1 } );
   }
	sort { kanaCmp( $a, $b ) } @wordList; # ← 使用例

◆ OpenOffice Basic の場合

 OpenOffice のマクロ関数を使うとしたら,こんな感じ。ここで asc という関数は UNICODE にも対応している。表計算で,ひらがな表記の「読み」が A 列にあるとしたら,“=KEY0( A1 )”と“=KEY1( A1 )”といった式を設定したセル列を作って,それぞれ最優先,第2優先の列としてソートすることで使える。

▼ OpenOffice Basic 表計算マクロ関数
   function key0( str1 as string ) as String
   Dim res As String
   res = ""
	for n = 1 to len( str1 )
	p = asc( Mid( str1, n, 1 ) )
	  if 12352 < p and p <= 12438 then
	  res = res & Mid( "ああいいううええおおかかききくくけけここささししすすせせそそたたちちつつつててととなにぬねの"& _
		"はははひひひふふふへへへほほほまみむめもややゆゆよよらりるれろわわゐゑをんうかけ", p-12352, 1 )
	end if
	Next
   key0 = res
   end function
   function key1( str1 as string ) as String
   Dim res As String
   res = ""
	for n = 1 to len( str1 )
	p = asc( Mid( str1, n, 1 ) )
	  if 12352 < p and p <= 12438 then
	  res = res & Mid( "10101010100202020202020202020202021020202000000230230230230230000010101000000100000211", p - 12352, 1 )
	  end if
	Next
   key1 = res
   end function


© M.Ishikawa; TREEWARE 2021.