単数形⇔複数形の変換メソッドを作ってみた

長い 前置き

相変わらず合宿報告をしないまま別のエントリです。

弊社のデータベースに於けるテーブル名の命名規約として、「基本的に複数形で定義する」というルールが存在します。

まぁ、私が勝手に考えて勝手に始めたことなので仲間のみんなには半ば強引に納得して貰ってる感がありますが、気にしたら負けだと思っています。

んで、システム開発を行うに当たって、いわゆるフレームワークと呼ばれるモノを作って *1 おり、その中での根幹機能に完全自作の O/R マッパーがあります。

O/R マッパーってのは、ザックリと説明するなら「Object と Relational-database の Mapping を行うモノ」っていう代物です。

データベースの各テーブル・各行をオブジェクトと見なして、オブジェクト指向な言語でのプログラムに於いて SQL を意識せずにデータベース操作を行えるようにするわけですね。*2

んで、その O/R マッパーはテーブル単位でクラスを作ってるんですが、そのクラス名は「テーブル名を単数化してアンダースコアで分割して各単語の頭文字を大文字にする *3」という命名規約を遵守する形で定義されています。

ってことは、単数形⇔複数形の変換が必要になるわけです。

………。長い前置きですね。

ってことで本題。

そもそも単数形⇔複数形の基本変換ルール

これはプログラムではなく英語のお勉強になるわけですが、任意の単語を単数形から複数形に変換する場合には基本的に以下のルールが適応されます。

  • 末尾に s を付ける
  • 但し、末尾が s, x, sh, ch, o で終わる場合には es を付ける
  • また、末尾が y で終わる場合には y を i に変えて es を付ける
  • 例外として、person -> people とか man -> men とか knife -> knives のような不規則変化もある

と、こんな感じのコトを中学校で習ったような気がします。

が、いかんせん英語の成績が常に 2/5 だった私には不得手な話だったりもします。

そもそも自然言語は例外が多すぎるので、「答えが一つに定まる」という点に於いて数学が好きな私にとって、根本的に相性が悪いとか思うですよ。

………話が逸れました。

では、このルールに則って変換を考えてみます。

まず、一番厄介なのは例外的な不規則変化ですね。

これはどーしよーもないので、辞書を作って対応するのがベターでしょう。

他の三件に関しては機械的に変換出来そうです。

PHP によるサンプル

じゃあ、実際にプログラムに落とし込んで考えてみます。

<?php
// {{{ $dictionary
// 一部抜粋
$dictionary = array(
    'child'      => 'children',
    'crux'       => 'cruces',
    'foot'       => 'feet',
    'knife'      => 'knives',
    'leaf'       => 'leaves',
    'louse'      => 'lice',
    'man'        => 'men',
    'medium'     => 'media',
    'mouse'      => 'mice',
    'oasis'      => 'oases',
    'person'     => 'people',
    'phenomenon' => 'phenomena',
    'seaman'     => 'seamen',
    'snowman'    => 'snowmen',
    'tooth'      => 'teeth',
    'woman'      => 'women',
);
// }}}

// {{{ singular2plural
/**
 * 単数形の英単語を複数形に変換する
 *   FIXME: マルチバイトを一切考慮してないのでそのままじゃ使えません
 *
 * @param string $singular 単数形
 * @return string 複数形
 */
function singular2plural($singular) {
    $plural = "";
    if (array_key_exists($singular, $dictionary)) {
        $plural = $dictionary[$singular];
    } elseif (preg_match('/(s|x|sh|ch|o)$/', $singular)) {
        $plural = preg_replace('/(s|x|sh|ch|o)$/', '$1s', $singular);
    } elseif (preg_match('/y$/', $singular)) {
        $plural = preg_replace('/y$/', 'ies', $singular);
    } else {
        $plural = $singular . "s";
    }
    return $plural;
}
// }}}

こんな感じですかね。

ファンクションコメントに書いたようにマルチバイトを一切考えてないので、このままじゃ使えないとは思いますが :-P

まとめ

正直、ここまで書いて「エントリ残すほどのモノでも無かったなぁ…。」とか思っちゃいましたが、消すのも勿体ないのでそのまま保存しちゃいますw

ま、ポイントは辞書変換を優先的に行ってるところですかね?

ラテン語を語源とする英単語は、もっと複雑な変化を起こすとか聞いたことがあるので、機械的に変換出来ない単語に関しては人力に頼るしかないのが実情ってわけですね。

やっぱり完璧な機械翻訳エンジンへの道のりは遠いってことです (ぇ

*1:正確には既存の F/W を改修しまくってるだけですが

*2:って言うと若干語弊がある気もするけど。

*3:アッパーキャメライズとか言ったりします