C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

複数の配列をソートする方法

[トピック内 6 記事 (1 - 6 表示)]  << 0 >>

■85978 / inTopicNo.1)  複数の配列をソートする方法
  
□投稿者/ こんなのお (1回)-(2017/12/06(Wed) 19:41:17)

分類:[.NET 全般] 

            Dim DateMod(1000) As Date
            Dim filepath(1000) As String

というような配列を宣言し、
DateModの日時順で
複数の配列をソートしたいのですが
普通にやるなら以下のように一つずつ地道にする方法があります。

配列が二つくらいなら良いですが
これが10個とか20個になってくると
コードが見づらいですし、
後からの修正も大変ですので
もっとスマートな書き方をしたいのですが何か良い方法はありますでしょうか?




            For i = 1 To 1000

                For j As Integer = 1000 To i Step -1

                    If DateMod(i) > DateMod(j)  Then

                        Dim swap1 As Date = DateMod(i)
                        DateMod(i) = DateMod(j)
                        DateMod(j) = swap1

                        Dim swap2 As String = filepath(i)
                        filepath(i) = filepath(j)
                        filepath(j) = swap2

                    End If
                Next j
            Next i


引用返信 編集キー/
■85983 / inTopicNo.2)  Re[1]: 複数の配列をソートする方法
□投稿者/ なちゃ (234回)-(2017/12/06(Wed) 21:11:46)
配列ふたつならArray.Sort(Array, Array)系のメソッドでキー配列を元に要素配列のソートとかできますが、もっと数が多い場合はこれではできませんね。
各配列にいろんなデータが入ってる構造のようですが、出来ればデータ要素をまとめたクラスまたは構造体の、単一の配列という構造にする方が色々と扱いやすいです。

もっともこれは、ソート後にデータを扱う際に個別の配列でないと困るといった前提があるならだめですが。

引用返信 編集キー/
■85984 / inTopicNo.3)  Re[1]: 複数の配列をソートする方法
□投稿者/ shu (1073回)-(2017/12/06(Wed) 21:39:25)
No85978 (こんなのお さん) に返信

なちゃさんの言うようにデータをクラス化してひとまとめにして扱うのがよいと思いますが
提示された内容をいかしておこなうなら以下のような方法もあります。

a,bがデータです。他にあっても全然かまいません。
sortidxsがbをソートとした結果の配列のインデックスの配列となります。(実際にはbはソートされません)
sortidxsに設定されている順番にa,bから該当する要素を取り出せばそれはbをソートした順番に取り出せることになります。
sortidxsを求めるときのOrder Byの部分を変更すればaでのソートをすることもその他の配列でソートすることもできます。

        Dim a = {5, 2, 1, 6, 21, 4}
        Dim b = {#2017/10/1#, #2017/10/2#, #2017/10/10#, #2017/10/5#, #2017/10/8#, #2017/10/3#}

        Dim sortidxs = (From idx In Enumerable.Range(0, a.Length)
                        Order By b(idx)).ToArray

        For idx = 0 To sortidxs.Length - 1
            Dim idx2 = sortidxs(idx)
            Console.WriteLine($"{a(idx2)} {b(idx2)}")
        Next

引用返信 編集キー/
■85985 / inTopicNo.4)  Re[2]: 複数の配列をソートする方法
□投稿者/ こんなのお (2回)-(2017/12/06(Wed) 21:51:56)
ありがとうございます。

クラスを使う場合、
Dim swap1 As Date = DateMod(i)
DateMod(i) = DateMod(j)
DateMod(j) = swap1

のようにスワップするにはどうしたら良いですか?

引用返信 編集キー/
■85986 / inTopicNo.5)  Re[3]: 複数の配列をソートする方法
□投稿者/ はるまきとかげ (3回)-(2017/12/06(Wed) 23:35:39)
No85985 (こんなのお さん) に返信

クラスを使うならLINQに丸投げしちゃいましょう

Class Item
    Public Property DateMod As Date
    Public Property filepath As String
End Class

Sub Main()
    Dim Data = {
        New Item() With {.DateMod = New Date(2017, 12, 3), .filepath = "c:\a.txt"},
        New Item() With {.DateMod = New Date(2017, 12, 2), .filepath = "c:\b.txt"},
        New Item() With {.DateMod = New Date(2017, 12, 1), .filepath = "c:\c.txt"}
    }

    Dim dateSorted = Data.OrderBy(Function(item) item.DateMod)

    For Each item In dateSorted
        Console.WriteLine(item.filepath)
    Next

    Console.ReadKey()
End Sub

引用返信 編集キー/
■85990 / inTopicNo.6)  Re[1]: 複数の配列をソートする方法
□投稿者/ 魔界の仮面弁士 (1497回)-(2017/12/07(Thu) 14:00:38)
No85978 (こんなのお さん) に返信
> For i = 1 To 1000
i = 0 のデータは、ソート対象外なのですね?

> Dim DateMod(1000) As Date
> Dim filepath(1000) As String
他の方も書かれているように、個別の変数にするのではなく、
クラスにまとめるべきかと思います。
(クラスの配列から、個々の要素の一次元配列を作るのは簡単ですし)


あえて元の配列を活かすのであれば、こんな書き方もあります。
※最初のコードにあわせ、DateMod(0) と filepath(0) はソート対象外としています。

Dim sortedIndex() As Integer = (
 From o In DateMod.Select(Function(d, i) New With {d, i}).Skip(1)
 Order By o.d, o.i Select o.i).ToArray()


これにより、ソートされたインデックス番号が sortedIndex に入るので、
 For Each idx As Integer In sortedIndexByDate
  Console.Write("{0}: #{1}#, ""{2}""", idx, DateMod(idx), filepath(idx))
 Next
などのようにして取り出すことが出来ます。


さらに上記を使って、インデックス番号順に並び替えた配列として
受け取りたいなら、このように書けます。

Dim SortedDateMod() As Date = New Integer() {0}.Concat(sortedIndex).Select(Function(i) DateMod(i)).ToArray()
Dim Sortedfilepath() As String = New Integer() {0}.Concat(sortedIndex).Select(Function(i) filepath(i)).ToArray()
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ