2016/02/09

[C#]2つの集合の差分を調べる

このエントリーをはてなブックマークに追加
集合が2つあって、片方にはなくて、もう片方には存在する要素の差分を調べます。
例として、常用漢字にある漢字で、JIS第1水準にはない漢字を調べるコードを書きます。

常用漢字とJIS第1水準とはなにかをざっくり


常用漢字
https://ja.wikipedia.org/wiki/%E5%B8%B8%E7%94%A8%E6%BC%A2%E5%AD%97

常用漢字とは「現代の国語を書き表す場合の漢字使用の目安」として、国が選定した漢字です。2136字あります。

JIS漢字コード
https://ja.wikipedia.org/wiki/JIS%E6%BC%A2%E5%AD%97%E3%82%B3%E3%83%BC%E3%83%89

JIS漢字コードの第1水準漢字とは、日本工業規格において定められた漢字コードのうち使用頻度が高いとされている漢字です。2965字です。

常用漢字はよく使われる目安として出版物や教育に関わるようです。方や、JIS漢字コードはコンピュータ上の日本語表示の文字コードとして作られていたもの。第4水準という一度も見たことのない漢字まで一通り決められています。ざっくり理解ですが、作られた目的は全然違うようです。
しかし、どちらもよく使われる漢字同士なので似通った集合なわけですね。

常用漢字は2136字で、JIS漢字コードの第1水準漢字は2965字です。もちろん、最初から人力で調べる気はありませんので、プログラムに頼りましょう。

コード


常用漢字とJIS漢字コードの第1水準漢字のリストは、こちらのサイトを参考にさせていただきました。

漢字辞典オンライン
http://kanji.jitenon.jp/

漢字のリストは、2つともテキストファイルにしてます。
ここに置いておきます。

// using System.IO;

private void button1_Click(object sender, EventArgs e) {
        
    string joyo = this.ReadFile("常用漢字(2136字).txt");
    string jis = this.ReadFile("JIS第1水準(2965字).txt");

        // 差分を拾う
    string sabun = new string(joyo.Where(n => !jis.Contains(n)).ToArray());

    Console.WriteLine(sabun);
}

private string ReadFile(string file) {
    StreamReader reader = new StreamReader(file);
    string text = reader.ReadToEnd();
    reader.Close();

    // 改行を省いておきます
    text = text.Replace(System.Environment.NewLine,"");

    return text;
}

実行結果

上のコードを実行した結果です。

丼刹拉訃恣哺惧羞貪喩彙楷毀嗅傲慄箋瘍辣憬摯踪嘲諧錮緻曖璧籠鬱

はい。
30文字ヒットしました。

解説

解説と言うほどのことはしていませんが、コードはサンプルとなる文字列を拾ってくる部分がほとんどです。
「常用漢字(2136字).txt」、「JIS第1水準(2965字).txt」のファイルは実行ファイルの直下に必要です。
ファイルの存在確認すらしてないコードなのでご注意ください。

なんだかんだで、主要な処理は下の一行です。
string sabun = new string(joyo.Where(n => !jis.Contains(n)).ToArray());

joyoにある文字を走査して、jisに存在していない漢字を文字列として再構築しています。
  • stringはcharの配列として利用できますので、そのままLinqのWhereメソッドを利用します。
  • jis.Contains(n)は、joyo内の1文字(n)がjis内に含まれていたらtrueを返します。
  • joyo.Whereメソッドは、否定演算子(!)があるので含まれなかったものだけを戻していきます。
  • 最後に、charの配列から文字列stringを生成してます。


途中にある否定演算子(!)をなくせば、「どちらにも存在する要素を調べる」コードに早変わりします。
string sabun = new string(joyo.Where(n => jis.Contains(n)).ToArray());

こちらのコードでは、常用漢字とJIS第1水準のどちらにも該当する漢字が抽出できます。

おまけに


サンプルとして使用した常用漢字と第1水準漢字のことばかり喋っていますが…。
(知らなかった分、気づきが多かったです)

JIS第1水準は3000字近くあるので、常用漢字を包含しているかと思いきや、そういうわけでもないんですね。
というのも、常用漢字は最近(2010年)に改定されていて、差分文字の多くはそのときに追加されたもののようです。
  • 「丼」とか。たしかに近年になって頻度が増えたのでしょう。
  • 「嵐」とか「韓」とか。流行りとかではないのかもしれないけれど、文化ってそういうものですものね。
  • 「鬱(うつ)」が常用に、というのはいい気はしません。

もちろんJISの漢字コードを改定するわけにいかないですからね。


はい、以上です。
お粗末さまでした。

0 件のコメント :

コメントを投稿