何となく Blog by Jitta
Microsoft .NET 考

目次

Blog 利用状況
  • 投稿数 - 761
  • 記事 - 18
  • コメント - 35963
  • トラックバック - 222
ニュース
  • IE7以前では、表示がおかしい。div の解釈に問題があるようだ。
    IE8の場合は、「互換」表示を OFF にしてください。
  • 検索エンジンで来られた方へ:
    お望みの情報は見つかりましたか? よろしければ、コメント欄にどのような情報を探していたのか、ご記入ください。
It's ME!
  • はなおか じった
  • 世界遺産の近くに住んでます。
  • Microsoft MVP for Visual Developer ASP/ASP.NET 10, 2004 - 9, 2011
広告

記事カテゴリ

書庫

日記カテゴリ

ギャラリ

その他

わんくま同盟

同郷

 

ネタもと:リストボックスが正しくソートされない

ネタは、大吉末吉さんの仮説[2007/08/21(火) 21:13:08]ListBoxのソートをする時の文字の順番は一方方向ではなく、じゃんけんの様にループする場合がある。


ループするという表現は、なかなかおもしろいですね。本当は、「評価されないので、評価される順序によって順番が決まる」ってことです。

K.J.K.さんの解説[2007/08/21(火) 19:40:47]から、評価されない文字がある、ということがわかります。では、「評価されない」とは、どのようなことでしょうか。ここで、IComparable インターフェイスを調べてみます。

IComparable.CompareTo Method より:

ValueMeaning
Less than zeroThis instance is less than obj.
ZeroThis instance is equal to obj.
Greater than zeroThis instance is greater than obj.

比較するためには、他の値と比べる必要があります。比べた結果、他方の値よりも前なのか、同じなのか、後ろなのかを、評価の結果とします。評価の結果は、ここにある通り3つです。より小さいか、同じか、より大きいか。ここでは .NET Framework を例に取りましたが、どのような言語であっても、独自に比較関数を追加できるものであれば、この3つ値のどれかを返すように定義するようになっていると思います。

いま、"a", "b", "c" の3つの文字を比較するとします。これを、"b", "a", "c" の順に追加していくとしましょう。
まず、"b" を追加します。このとき、比較の対象はありません。従って、先頭に追加されます。
次に、"a" を追加します。"b" に対して CompareTo("a") を実行すると、「Greater than zero」が返ってきます。このため、"a" は "b" より小さいと判断され、"b" の前に "a" が追加されます。
次に、"c" を追加します。"a" に対して CompareTo("c") を実行すると、「Less than zero」が返ってきます。このため、"c" は "a" よりも大きいと判断されます。そして "a" の次にある "b" と比較されます。これも「Less than zero」が返ってくるので、"b" の後ろに "c" が追加されることになります。

さて、問題の "[", "a", "「" です。この場合、"[" と "「" が、「評価されない文字」となっています。先ほどの評価の結果には「評価しない」がないため、「評価しない」ための方法が、いくつか考えられます。

まず、「評価できる文字よりも、小さいと判断する。評価できない文字同士では、同じと判断する」。
そして、「評価できる文字よりも、大きいと判断する。評価できない文字同士では、同じと判断する」。
最後に、「どの文字に対しても同じと判断する」。

実装するには、最後の「どの文字に対しても同じと判断する」のが、とても楽です。そして、Windows の実装は、そのようになっているようです。

では、「同じ」と判断されるとして、どうなるか追ってみましょう。

まず、"[" です。最初なので、先頭に追加されます。
次に、"a" です。CompareTo("[") の結果は「Zero」です。同じなので、次の項目との比較に回します。しかし、次はないので、後ろに追加します。
そして、"「" です。CompareTo("[") の結果は「Zero」です。同じなので、次の項目との比較に回します。CompareTo("a") の結果は「Zero」です。同じなので次の項目…がないので、後ろに追加します。

どうも、こんな実装になっているようですね。K.J.K.さんの[2007/08/22(水) 11:06:25]にある、3,でたらめ。しかも再現性なし。同じ入力でもやるたびに出力が変わる。に注目です。件の ListBox は、同じ入力であれば同じ順序で表示されるため、「ソートされている」と言えるわけです。

さて、タイトルの「ソートの結果は一定しないことがある」ですが。

「同じ」と判断されるものについては、後先どちらになるか、使用するアルゴリズムによって扱い方が決まります。様々なソート アルゴリズムについて、表示するものが違うけど、比較するものが違うオブジェクトを用意して実験してみればわかるでしょう。また、「安定ソート」について、調べてみるのもいいでしょう。ListBox のように、一つずつ追加していく場合、追加した順になることが多いです。一方、すでにある配列をソートするクイックソートでは、一定しない実装があります。

ということは、です。オリジナルなクラスの、オリジナルなソートを追加するときには、どうやって順序を決めるか、よく考えなければならない、ということです。

投稿日時 : 2007年8月27日 23:05
コメント
  • # re: ソートの結果は一定しないことがある(ぇ?
    渋木宏明(ひどり)
    Posted @ 2007/08/28 4:08
    .NET の標準ライブラリの xxx.Sort() って、破壊型のソートなんですよね。

    たまに安定型のソートが欲しくなる時が。。。 (^^;
  • # re: ソートの結果は一定しないことがある(ぇ?
    はなおか じった
    Posted @ 2007/08/28 7:28
    渋木さん、まいどお世話になります。
    安定ソートの反意語がでてこなかった。(._.)φ破壊

    ListViewなんかで、ソートさせる順番によって並び方が変わるってことが起こり得ますね。


    なんだか、「便利=基礎を隠す」なのか?と考える、今日この頃。
  • # re: ソートの結果は一定しないことがある(ぇ?
    裏口
    Posted @ 2007/08/28 9:54
    このネタ結構あちこちで取り上げられてますが、じったさん
    の切り口は結構新鮮に感じました。
    同値がFIFOのケースは多いですが、確かにこのケースじゃ
    誤解されても仕方ないかも。
    # 問題はVB5~6の世界みたいですが、.NET系も同様なので
    # しょうか?
  • # re: ソートの結果は一定しないことがある(ぇ?
    Orator
    Posted @ 2010/06/19 0:02
    # あれ、元ネタは削除されていたのか。。。

    》2007/08/23(木) 02:52:01
    > ところが、Sorted = True 時における『[』の登録には問題があるため、
    (中略)
    > これ自体は、VB1.0 / Win3.0 の頃から報告されていた問題のようで、実際にKB にも登録されていますね。

    今更ですが、元ネタに書いた KB というのは下記の文書を指しています。
    http://support.microsoft.com/kb/74132/en-us
  • # re: ソートの結果は一定しないことがある(ぇ?
    Jitta
    Posted @ 2010/06/19 21:44
    魔界の仮面弁士さん、補足ありがとうございます。

    ええ、このエントリを登録した頃に、削除されてしまっていました(苦笑)
タイトル
名前
Url
コメント