DOBON.NET DOBON.NETプログラミング掲示板過去ログ

配列内の数字を綺麗にソートしたい

環境/言語:[C# FrameWork1.1]
分類:[.NET]

C#(2003)には配列のソートの手段は自前で無い場合はArray.sortしか無いのでしょうか?
Array.sortだと
ソート前・・・16 23 24 29 9 27
ソート後・・・16 23 24 27 29 9
となります。
9は29より小さいのにArray.sortは29は9より小さいとして並び替えています。
使い物にならないですが、自分で実装するはちょっと難易度が高そう(1時間
位考えて手が止まった)なので、他にいいソートがあればそれを使う、なければ
あきらめてArray.sortを使うという方向です。
>C#(2003)には配列のソートの手段は自前で無い場合はArray.sortしか無いのでしょうか?
自前でないという表現がよくわかりませんが、
自分でカスタマイズした比較をしたいならば、要素の比較方法を指定したIComparerインターフェイスを、Array.Sortの引数渡してソートしてください。

参考)
コレクション(または配列)内の要素を方法を指定して並び替える(または検索する)
http://dobon.net/vb/dotnet/programing/icomparer.html
ちゅうか、文字列じゃなくて、数値としてArrayListに入れれば、
いいのでは?

System.Collections.ArrayList al = new System.Collections.ArrayList();

al.Add( 16 ); // 文字列の 16 ならば、 Int32.Parse や Convert.ToInt32で数値に変換して入れる。
al.Add( 23 );
al.Add( 24 );
al.Add( 29 );
al.Add( 9 );
al.Add( 27 );

foreach ( System.Object o in al )
{
    System.Console.WriteLine( o.ToString() );
}

System.Console.WriteLine( "" );
al.Sort();

foreach ( System.Object o in al )
{
    System.Console.WriteLine( o.ToString() );
}
2006/08/22(Tue) 16:50:45 編集(投稿者)

■No17208に返信(やきそばソースさんの記事)
> 9は29より小さいのにArray.sortは29は9より小さいとして並び替えています。

数値と見なしていないからでしょう。
つまり、"09" < "29" ですが、"9" > "29" です。
文字列で考えれば、何ら不思議ではないですよね?

> 使い物にならないですが、自分で実装するはちょっと難易度が高そう

独自のクラスを使っているならば、ToString メソッドを弄るだけで何とかなりますが、
IComparer インターフェイスを実装するのが王道だと思います。
後者については、Blue さんの書き込みどおりです。
■No17211に返信(Blueさんの記事)
> ちゅうか、文字列じゃなくて、数値としてArrayListに入れれば、
> いいのでは?

文字列になっているのはこの配列のソート結果を取り出して、","を挟んで繋ぐためです。

16 23 24 27 29 9だったら16,23,24,27,29,9とする仕組みが後ろにあります。

つまり (スタート)文字列配列>数値配列に変換>処理>文字列配列に再変換

という感じでOKでしょうか。
2006/08/22(Tue) 17:13:41 編集(投稿者)

勝手にArrayListでやってもうてた。。。

> つまり (スタート)文字列配列>数値配列に変換>処理>文字列配列に再変換
数値配列から
> ","を挟んで繋ぐためです
ことはできないのでしょうか?
----> string.Join使っているってことね。
# C#2.0ならArray.ConvertAllあたりで、、、てそんなことするならICompareを実装したほうがすっきりするか。

まぁ、変換が無駄に感じるようであれば、IComparerをちょいっと作っちゃえばいいですよ。
まずFor文でInt.Parseを使って文字列配列を数値配列に、
Array.Sort
その後、For文でToStringを使って文字列配列に戻しました。

for(int count=0 ; count<WinningNumber ; count++)
{
    Result += HitScore[count]; //Resultはstring

    if(count != WinningNumber-1)
    {
        Result += " , ";
    }
}
という処理で","をつけているので文字列のほうが都合がいいと
思って文字列配列を使用しました。
解決済み!
一応、IComparerを使った方法を載せておきます。
(せっかくなので)

public class Sample
{
    public static void Main( string[] args )
    {
        string[] al = { "16", "23", "24", "29", "9", "27" };

        System.Console.WriteLine( "ソート前:{0}", string.Join( ",", al ) );
        System.Array.Sort( al, new SNumCompare() );
        System.Console.WriteLine( "ソート後:{0}", string.Join( ",", al ) );
    }
    
    private class SNumCompare : System.Collections.IComparer
    {
        public int Compare( object x, object y )
        {
            return System.Convert.ToInt32( x ) - System.Convert.ToInt32( y );
        }
    }
}

# C++/CLIになれちゃっているせいか、つい System:: のように :: を書いてしまふ。。。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板