単語数の多い辞書データの並べ替え

使用する辞書ファイル

ejdic2knotsort.txtの内容は次のようなものです。2002件あります。

ejdic2k.txtのabc順になっていないものです。リンクを右クリックして出てくるメニューから「名前をつけてリンク先を保存」を選ぶことで、javaプログラムを入れるフォルダにダウンロードしておきましょう。

英単語と意味の間はタブで区切ってあります。

a	一つの,ある
complicate	…'を'複雑にする
clothe	…‘に'衣服を着せる,…'を'すっかりおおう,一面におおう
upset	…‘を'ひっくり返す,だめにする,心お乱す,転倒,混乱
frighten	…‘を'ひどく驚かせる,おびえさせる,ひどく怖がる
think	…‘を'考える,思う,…‘を'企てる,考える
can	…することができる,…であり得る,…してもよい
whenever	…するときはいつでも;,いち…でも
because	…だから,…ゆえに,であるからといって
would	…だろう,…するつもりである,…したものだった,…したい
at	…で,…に,…の最中で,…の状態に,…を目指して,…によって
without	…なしに,もし…がなければ,…を外に,…[の限度]を越えて
though	…にもかかわらず,たとえ…でも,もっとも…ではあるが
to	…に対して,…まで,…のために,…へ,…に
toward	…のほうへ,…のほうに,…近く,…に対して
.....................省略.........

交換法で並べ替え

ファイル読み込み部分は Jiten05.java または Jiten04.java とほとんど同じです。

並べ替え部分は Koukan05.java とほとんど同じです。ただし途中経過は i が変わった時に word[i] と i の値を表示しています。 Koukan05.java のままだと 2002個のデータを表示しますから多すぎるからです。また、並べ替えた結果の報告は最初の数行と最後の数行だけにしています。これも多すぎるからです。

? の部分は Koukan05.java と同様に書き換えます。

一部全角のスペースが紛れているようです。半角に直してください。「\12288 は不正な文字です」の \12288 は全角スペースのことです。

ファイル名 DicSort01.java

import java.io.*;

public class DicSort01 {
    public static void main( String[] args ) {
        //Jiten05.java のファイル読み込み部分
        String fname = "ejdic2knotsort.txt";
        String[] word = new String[2010];
        String[] imi  = new String[2010];
        int ct = 0;
        try {
            FileReader   in  = new FileReader(fname);
            BufferedReader inb = new BufferedReader(in);
            String line;
            while ((line = inb.readLine()) != null) {
                //System.out.println(line);
                String[] ndata = line.split("\t");
                word[ct]=ndata[0];
                imi[ct]=ndata[1];
                ct++;
            } 
            System.out.println("以上 0〜" + (ct-1) + " の " + ct + " 行");
            inb.close();
            in.close();
        }
        catch (IOException e) {
            System.err.println( fname + " がないのでは?" );
            System.err.println( e);
        }
        //Koukan05.java の交換部分
        int n = ct;  //word.length だった
        for( int i=n-2; i>=0; i-- ){
            System.out.println( word[i] + "\t" + i ); //途中経過
            for( int j=0; i>=j; j++ ) {
                // print(word,i,j);
                if( word[j].compareTo(word[j+1]) > 0 ){
                    String tmp   = word[j];
                    word[j]   = word[j+1];
                    word[j+1] = tmp;
                    tmp       = imi[?];
                    imi[?]    = imi[?];
                    imi[?]  = tmp;
                }
                // print(word,i,j);
            }
        }
        //結果の報告部分(一部だけ報告)
        System.out.println("=-=-=-=-=-=-=-=-=-=");
        for (int x = 0; 10>x; x++) {
            System.out.println(word[x]+"\t"+imi[x]);
        }
        System.out.println("=-=-=-=-=");
        for (int x = ct-5; ct>x; x++) {
            System.out.println(word[x]+"\t"+imi[x]);
        }
    }//mainの終わり
  //printは全部削除
}//classの終わり

コンパイルと実行は次のようにします。

$ javac DicSort01.java 
$ java DicSort01
....(途中経過を表示しますが長いので最初の部分は省略)......... 
absent	10
absence	9
abroad	8
above	7
about	6
able	5
ability	4
a	3
I	2
English	1
Christmas	0
=-=-=-=-=-=-=-=-=-=
Christmas	クリスマス
English	英語,イギリス人,イギリスの,イギリス人の,英語の
I	私は
a	一つの,ある
ability	能力
able	できる,有能な
about	について,およそ,around
above	の上方へ,の上に,前に
abroad	海外へ(で),外国に(で),広く,広まって
absence	るす,欠席,ないこと
=-=-=-=-=
yield	産出する,明け渡す,作物がてきてる,屈する
you	あなた[がた]は(を)
young	若い,年下のほうの
youth	若さ,青年時代,青年
zero	0,零,零度
$ 

Christmas, English, I が辞典のabc順と異なります。これは .compareTo() が文字コードの値の差を返すからです。つまり文字コード順なのです。

このままで、.compareTo() を使って二分探索をするのならば、何の問題もありません。Christmas も I も検索できます。もちろん、christmas や i は見つからないことになります。

christmas でも Christmas でも二分探索で検索できるようにするには2つの解決策考えられます。

(1)辞書に両方とも登録する
(2)大文字小文字を区別せずに比較をするメソッドを使う。
compareTo() -> compareToIgnoreCase()
equals() -> equalsIgnoreCase()
ただし、compareToIgnoreCase() で作った辞書は equalsIgnoreCase() で検索しないと見つからない単語が出ます。

人間の目で検索するのか、二分探索をするのか、他のアルゴリズムで使うのか、使用方法を考えて並べ替える必要があります。

濁点の扱い

equalsIgnoreCase() は英語の習慣を救うだけです。日本人にはアルファベットとして同じに見えるフランス語やドイツ語にも異なる文字や習慣があります。まして、アラビア文字やハングル、ひらがな、カタカナなどの問題は一層難しくなります。ひらがなの濁点の処理を例に、文字コード順だけではうまく行かない場合について考えてみましょう。

ファイル名 Dakuten01.java

public class Dakuten01 {
    public static void main( String[] args ) {
        String[] word = { "じしょ", "じてん", "してん", "しんかい", "しさん", "じこく" };
        int n = word.length;
        for( int i=n-2; i>=0; i-- ){
            for( int j=0; i>=j; j++ ) {
                if( word[j].compareTo(word[j+1]) > 0 ){
                    String tmp   = word[j];
                    word[j]   = word[j+1];
                    word[j+1] = tmp;
                }
            }
        }
        for (int x = 0; word.length>x; x++) {
            System.out.println(word[x]);
        }
    }//mainの終わり
}//classの終わり

コンパイルと実行は次のようにします。

$ javac Dakuten01.java 
$ java Dakuten01 
しさん
してん
しんかい
じこく
じしょ
じてん

二分探索に使うのであれば、これでもまったく問題はありません。

日本人が使う国語辞典の見出しに使うならばこれではいけません。次のようになっている必要があります。これには .compareToIgnoreCase() のような簡単な仕組みはありません。

じこく
しさん
じしょ
してん
じてん
しんかい

ファイルに出力

英語以外の辞書順