Kanhiraその2、辞書の構造

2019年5月22日

※Kanhiraについては/tag/kanhiraを参照されたい。

これはJavaによる漢字/ひらがな変換ライブラリKanhiraの紹介の続きである。

Kahiraの使い方としては簡単で、

   KanwaDict dict = ....
   Kanhira kanhira = new Kanhira(dict);
   String hiragana = kanhira.convert("漢字仮名交じり文");

とすればよい。あとは、このKanwaDictという辞書をどう作るかだけなのだが、あらかじめkakasidictを読み込むためのモジュールを用意してある。

  KanwaDict dict = KakasiDictReader.load("dict/kakasidict");

kakasidictは単純に「かかし」用の辞書ファイルである。

辞書オブジェクトのインターフェース

辞書オブジェクトのインターフェースとしても単純であり、以下のようなもの。

public interface KanwaDict {

  /**
   * 漢字熟語の最初の一文字を入力し、その漢字から始まるすべての熟語情報を得る。
   * @param k 漢字熟語の最初の一文字
   * @return すべての熟語情報
   */
  public KanjiYomiList lookup(char k);
}

先頭文字を指定すると、それから開始するすべての登録語句のリストを返す。以下のようなものだ。

public class KanjiYomiList  {  
  private TreeSet<KanjiYomi>list = new TreeSet<>();

このリストは最長一致させるために、長い語句から先に並べられている。例えば、最初の文字が「悪」であれば、

  • 悪徳不動産屋
  • 悪天候時
  • 悪代官

などという順番になる。そして、それぞれの語句は以下の構造になる。

public class KanjiYomi implements Comparable<KanjiYomi> {

  /** 
   * 漢字、「悪代官」の場合は「悪代官」が格納される。
   * 「悪巧み」の場合は「悪巧み」、この場合の「み」は送り仮名ではなく漢字の一部。
   * また、「貴ノ花」の場合は「貴ノ花」だが、このようにカタカナがまじる場合もある。 
   * 送り仮名のある場合、たとえば「悪い」の場合は「悪」だけが格納される。
   */
  private final String kanji;

  /** よみ、上の例の場合、「あくだいかん」が格納される。 */
  private final String yomi;

  /** 
   * 送り仮名が無い場合は(char)0、ある場合はそのイニシャルの半角アルファベット小文字。
   * 例えば「悪い」の場合は「i」が格納される   */
  private final char okuriIni;

基本的に必要なものは以上である。この辞書を用意さえすればよい。

かかし辞書の読み込み

「かかし」辞書を読みこんで、上述の辞書オブジェクトを作成するために、KakasiDictReaderが用意されている。
単純に以下を呼び出せば、KanwaDictインターフェースを実装したKanjiYomiMapが返される。

  KanjiYomiMap yomiMap = KakasiDictReader.load(辞書ファイル名);

KanjiYomiMapの構造も極めてシンプルで以下のようなものだ。

public class KanjiYomiMap implements KanwaDict {

  private Map<Character, KanjiYomiList>map = new HashMap<Character, KanjiYomiList>(8192);

  public void add(char key, KanjiYomi kanjiYomi) {
    KanjiYomiList list = map.get(key);
    if (list == null) {
      list = new KanjiYomiList();
      map.put(key, list);
    }
    list.add(kanjiYomi);
  }

  @Override
  public KanjiYomiList lookup(char k) {
    return map.get(k);
  }