tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルArrayListのソート
記事No1172
投稿日: 2004/11/25(Thu) 17:32
投稿者みけ
[OSのVer]:Windows2000 Professional [VBのVer]:VB.NET2003

いつも参考にさせていただいてます。

以下のコードで、ArrayListに2次元配列を追加しソートしようとしています。
ソートキーは2次元配列の要素を指定しています。
値の設定されている要素では、うまくソートできるのですが
設定されていない(Nothingの)要素では、ソート結果が思うようにならないのです。

(フォームにソートボタンを貼付けています。)

    Private Sub btnSort_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles btnSort.Click
        Dim arrList As New ArrayList

        Dim i As Integer

        For i = 0 To 9
            Dim strTable(1, 0) As String
            strTable(0, 0) = i.ToString
            arrList.Add(strTable)
        Next

        Console.WriteLine("番号が設定されているインデックスで降順にソート")
        arrList.Sort(New IArrayComparer(0, 0, -1))

        For i = 0 To 9
            Console.WriteLine(arrList.Item(i)(0, 0))
        Next

        Console.WriteLine("ヌル値が設定されているインデックスで降順にソート")
        arrList.Sort(New IArrayComparer(1, 0, -1))

        For i = 0 To 9
            Console.WriteLine(arrList.Item(i)(0, 0))
        Next
    End Sub

    'ArrayListの2次元配列をソートするインターフェース
    Private Class IArrayComparer
    Implements IComparer
        Private m_intRow As Integer
        Private m_intCol As Integer
        Private m_shtSort As Short

        Public Sub New(ByVal intRow As Integer, ByVal intCol As Integer _
                        , ByVal shtSort As Short)
            m_intRow = intRow
            m_intCol = intCol
            m_shtSort = shtSort
        End Sub
        Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements

IComparer.Compare

            Dim objX(,) As Object = CType(x, Object(,))
            Dim objY(,) As Object = CType(y, Object(,))

            Dim objValueX As Object = objX(m_intRow, m_intCol)
            Dim objValueY As Object = objY(m_intRow, m_intCol)

            Dim intRet As Integer

            intRet = String.Compare(objValueX, objValueY)

            If m_shtSort = -1 Then    '降順
                intRet = -intRet
            End If

            Console.WriteLine("Compare:" & intRet.ToString & " X:&qu
ot; & objValueX & " Y:" &
objValueY)
            Return intRet

        End Function
    End Class

実行結果は、ヌル値が設定されている要素で降順にソートしても
ソートされないはずなんですが、元のArrayListの並びが
ばらばらになっているのです。
どなたか原因をご指摘いただけないでしょうか?
よろしくお願いします。

[ツリー表示へ]
タイトルRe: ArrayListのソート
記事No1178
投稿日: 2004/11/30(Tue) 15:29
投稿者るしぇ
Nothing だけじゃなくて同じ文字列だと結果は同じになるみたい。
arrList の作成部分で

For i = 0 To 9
    Dim strTable(1, 0) As String
    strTable(0, 0) = i.ToString
    strTable(1, 0) = "a"
    arrList.Add(strTable)
Next

ってやっても同じだったから。途中の出力見てると…
    arrList.Sort(New IArrayComparer(1, 0, -1))
の Sort がクイックソートだから?って気がしますが…
レス付いて無いから他の原因なのかな?…見当違いかも?(汗)

解決法ですが、自分でゴリゴリと…同じ値は並び替えないソートの
アルゴリズムを設計するか、いくつか並び替える項目がある
ならデータを DataTable に入れて DataTable.Select(String, String) メソッド
を使って、第2引数に並べ替え方向を指定する文字列を渡せば
お望みのような結果になると思います。
[参考]ソート
hhttp://web.hc.keio.ac.jp/~fujimura/lang/lec-n10s.html
[DataTable.Select メソッド (String, String)]
hhttp://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/cpref/html/frlrfsystemdatadatatableclassselecttopic3.asp

[ツリー表示へ]
タイトルRe^2: ArrayListのソート
記事No1184
投稿日: 2004/12/02(Thu) 02:17
投稿者たくボン
るしぇさんの補足です。

.NET(というかCLR)においてStringクラスは、不変で順序のある参照型として定義されています。
CLRにおいてStringクラスは他のクラスとは少々異なる動作をします。(通常Stringクラスを生成する場
合にはNewを使いませんよね?API等を利用する場合にNewしちゃう場面もありますが・・・)

String型に同じリテラル文字列を代入する場合、同じ文字列がマネージヒープ上(インターンプール)
に既に存在する場合、異なる変数でも同じインスタンスの参照を代入します。(これを文字列のインタ
ーン化と言います。ヘルプでStringクラスのInternメソッドを参照してみてください。またC#等で
ObjectクラスのReeferenceEqualsを使って参照の比較をしてみたらよく挙動がわかるかもしれません
ね。)

つまり、同じリテラル文字列(もしくはnull参照)を代入した値を使用して、Staring.Compare()を使用し
ても参照元が同じなので比較結果が常に等しいというのが原因と考えられます。

[ツリー表示へ]
タイトルRe^2: ArrayListのソート
記事No1199
投稿日: 2004/12/06(Mon) 12:58
投稿者みけ
るしぇさん(お世話になっています)、たくボンさん
ありがとうございます!

社員旅行にいっててレスが遅くなりました。
すみません。

初心者の私には、理解するだけで一苦労です(^-^;
るしぇさんに提案いただいたDataTableのソート機能
を使ってやってみます。

[ツリー表示へ]