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

配列のソートについて

環境/言語:[WIN2000 VB.NET2003]
分類:[.NET]

ARRAY.SORTは、一次元の配列に対応してます。
いまは、二次元以上の配列をソートしたいです。簡単な方法はありますか?
自分で作るのは、ちょっとめんどうくさいです。

よろしく。
  • 題名: Re[1]: 配列のソートについて
  • 著者: java.lang.Nullpo
  • 日時: 2004/08/30 11:08:07
  • ID: 5891
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
2004/08/30(Mon) 12:47:10 編集(投稿者)

■No5890に返信(johnさんの記事)
> ARRAY.SORTは、一次元の配列に対応してます。
> いまは、二次元以上の配列をソートしたいです。簡単な方法はありますか?
> 自分で作るのは、ちょっとめんどうくさいです。
>
> よろしく。

下記のように、それぞれの次元数に対応した関数を自分で作ってください。
下記は、3次元の場合です。

4次元の場合は、For文の中をSortTripleArray()に変えればできますし...
次元数が多くなってもそれぞれ前の次元数のソート関数を呼べばよいのです。

  Private Function SortTripleArray(ByVal nTplArray()() As String) As String()()
    Dim i As Integer

    For i = 0 To nTplArray.Length - 1
      Array.Sort(nTplArray(i))
    Next i

    Return nTplArray
  End Function
2004/08/30(Mon) 11:50:34 編集(投稿者)

2次元をソートするのが、Array.Sort(nDoubleArray) であることを考慮して、
10次元までソートする関数を組んでみた。
関数名を覚えるのが面倒だと思うので、オーバロード関数としております。
オーバーロードが嫌いでしたら、関数名を別名にしてください。

'--------------------------------------------------------------------------
  ' 3次元変数をソート
  Private Overloads Function SortString(ByVal nTripleArray()() As String) As String()()
    Dim i As Integer

    ' 1次元目の要素を指定して、2次元変数としてソート
    For i = 0 To nTripleArray.Length - 1
      Array.Sort(nTripleArray(i))
    Next i

    Return nTripleArray
  End Function
'--------------------------------------------------------------------------
  ' 4次元変数をソート
  Private Overloads Function SortString(ByVal nQuadrupleArray()()() As String) As String()()()
    Dim i As Integer

    ' 1次元目の要素を指定して、3次元変数としてソート
    For i = 0 To nQuadrupleArray.Length - 1
      Call SortString(nQuadrupleArray(i))
    Next i

    Return nQuadrupleArray
  End Function
'--------------------------------------------------------------------------
  ' 5次元変数をソート
  Private Overloads Function SortString(ByVal nQuintpleArray()()()() As String) As String()()()()
    Dim i As Integer

    ' 1次元目の要素を指定して、4次元変数としてソート
    For i = 0 To nQuintpleArray.Length - 1
      Call SortString(nQuintpleArray(i))
    Next i

    Return nQuintpleArray
  End Function
'--------------------------------------------------------------------------
  ' 6次元変数をソート
  Private Overloads Function SortString(ByVal nSextupleArray()()()()() As String) As String()()()()()
    Dim i As Integer

    ' 1次元目の要素を指定して、5次元変数としてソート
    For i = 0 To nSextupleArray.Length - 1
      Call SortString(nSextupleArray(i))
    Next i

    Return nSextupleArray
  End Function
'--------------------------------------------------------------------------
  ' 7次元変数をソート
  Private Overloads Function SortString(ByVal nSeptupleArray()()()()()() As String) As String()()()()()()
    Dim i As Integer

    ' 1次元目の要素を指定して、6次元変数としてソート
    For i = 0 To nSeptupleArray.Length - 1
      Call SortString(nSeptupleArray(i))
    Next i

    Return nSeptupleArray
  End Function
'--------------------------------------------------------------------------
  ' 8次元変数をソート
  Private Overloads Function SortString(ByVal nOctupleArray()()()()()()() As String) As String()()()()()()()
    Dim i As Integer

    ' 1次元目の要素を指定して、7次元変数としてソート
    For i = 0 To nOctupleArray.Length - 1
      Call SortString(nOctupleArray(i))
    Next i

    Return nOctupleArray
  End Function
'--------------------------------------------------------------------------
  ' 9次元変数をソート
  Private Overloads Function SortString(ByVal nNonupleArray()()()()()()()() As String) As String()()()()()()()()
    Dim i As Integer

    ' 1次元目の要素を指定して、8次元変数としてソート
    For i = 0 To nNonupleArray.Length - 1
      Call SortString(nNonupleArray(i))
    Next i

    Return nNonupleArray
  End Function
'--------------------------------------------------------------------------
  ' 10次元変数をソート
  Private Overloads Function SortString(ByVal nDecupleArray()()()()()()()()() As String) As String()()()()()()()()()
    Dim i As Integer

    ' 1次元目の要素を指定して、9次元変数としてソート
    For i = 0 To nDecupleArray.Length - 1
      Call SortString(nDecupleArray(i))
    Next i

    Return nDecupleArray
  End Function
'--------------------------------------------------------------------------

ある法則に気付くはずです。
前の次元数の関数を呼べば事実上、どんな次元数でも簡単に関数化できます。
ちなみに、インスタンスが生成されていない場合は例外になりますので、
[次元変数] Is Nothingでインスタンスが生成されているかを見る必要があります。

# しかし、最近の言語はすごいなぁ...
javaさん、返事ありがとうございました。

意味がわかりましたが、実際にやるのはちょっとエラーが出てました。
調べています。。。。。。

二次元の場合、簡単の例がよく教えてくれませんか?
よろしく。
■No5896に返信(johnさんの記事)
> javaさん、返事ありがとうございました。
>
> 意味がわかりましたが、実際にやるのはちょっとエラーが出てました。
> 調べています。。。。。。
>
> 二次元の場合、簡単の例がよく教えてくれませんか?
> よろしく。

二次元の場合は、Array.Sort()メソッドになります。

  Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
    Dim i     As Integer
    Dim nBefore  As String
    Dim nAfter  As String
    Dim nString() As String = {"C", "Delphi", "BASIC", "Java", "Assembler", "Lisp", "Perl", "Pascal"}

    ' 中身を表示させるため、すべての要素を取得
    For i = 0 To nString.Length - 1
      nBefore &= i.ToString & ":" & nString(i) & ControlChars.CrLf
    Next i

    ' ソート前の中身を表示
    MessageBox.Show("ソート前・・・・・・・・" & ControlChars.CrLf & nBefore)

    ' ここでソート
    Array.Sort(nString)

    ' 中身を表示させるため、すべての要素を再度取得
    For i = 0 To nString.Length - 1
      nAfter &= i.ToString & ":" & nString(i) & ControlChars.CrLf
    Next i

    ' ソート後の中身を表示
    MessageBox.Show("ソート後・・・・・・・・" & ControlChars.CrLf & nAfter)
  End Sub



> 意味がわかりましたが、実際にやるのはちょっとエラーが出てました。
> 調べています。。。。。。

エラー(例外)の内容は、System.NullReferenceExceptionではないですか?
No.5893の最後に述べていますが、Is Nothingでインスタンスが生成されているか確かめてください。

もし、それ以外の例外が発生しているのでしたら、ソースをペーストしてください。
レスありがとう。

但し、↓は一次元じゃないでしょう?

Dim nString() As String = {"C", "Delphi", "BASIC", "Java", "Assembler", "Lisp", "Perl", "Pascal"}

私の理解は、二次元が↓のモノです:

Dim nString(,) As String = {{"C","01"}, {"Delphi","02"}, {"BASIC","03"}, {"Java","04"}, {"Assembler","04"}, {"Lisp","06"}, {"Perl","07"}, {"Pascal","08"}}

教えてください。
VBのヘルプを調べると、
『いわゆる 「多次元」 の配列には、「多次元配列」 と 「多段階配列」 の 2 つがある点です。』

[例] 多次元配列と多段階配列
1: Tbl(3,4) = 100 //多次元配列
2: Dat(3)(4) = 200 //多段階配列

javaさんのやりかたは、「多段階配列」に対応すると思います。
私の最初の問題は、「多次元配列」のソートの問題です。

よろしく。
2004/08/30(Mon) 18:38:59 編集(投稿者)

■No5898に返信(johnさんの記事)
> レスありがとう。
>
> 但し、↓は一次元じゃないでしょう?
>
> Dim nString() As String = {"C", "Delphi", "BASIC", "Java", "Assembler", "Lisp", "Perl", "Pascal"}
>
> 私の理解は、二次元が↓のモノです:
>
> Dim nString(,) As String = {{"C","01"}, {"Delphi","02"}, {"BASIC","03"}, {"Java","04"}, {"Assembler","04"}, {"Lisp","06"}, {"Perl","07"}, {"Pascal","08"}}
>
> 教えてください。

Oh, Sorry. 私の中では、二次元配列 → 一次元配列の一次元配列で考えています。
理由は、何かと利用しやすいですし、(事実、Sortメソッドもそのまま利用できる)
次元数を指定することで一段階少ない配列に、代入もできるからです。(関数で渡す際に便利)
ですので私個人は、nString( , )ではなく、nString()()でやることをお勧めします。

...が、それは押し付けになってしまいますので、一応私なりに回答を出しますと、

  Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim nString( , ) As String = { {"C","03"}, {"BASIC","02"}, {"Java","05"}, {"Asm","01"}, {"Delphi","04"} }

    ' ソートする関数をコール
    nString = SortArrayString(nString)
  End Sub

  ' 2次元String配列をソート
  Private Function SortArrayString(ByVal nDblArray(,) As String) As String(,)
    Dim i As Integer
    Dim iMax As Integer
    Dim nArray1() As String
    Dim nArray2() As String

    iMax = (nDblArray.Length \ 2) - 1

    ReDim nArray1(iMax)
    ReDim nArray2(iMax)

    For i = 0 To iMax
      nArray1(i) = nDblArray(i, 0)
      nArray2(i) = nDblArray(i, 1)
    Next i

    Array.Sort(nArray1)
    Array.Sort(nArray2)

    For i = 0 To iMax
      nDblArray(i, 0) = nArray1(i)
      nDblArray(i, 1) = nArray2(i)
    Next i

    Return nDblArray
  End Function

もし、一次元目だけをソートしたければ、nArray2に関する記述を消去してください。
また、やはりこのやり方だと、他の変数に移し変える必要が出ますので、
速度も遅いですし、流用がしづらいです。
また、三次元配列でやる場合は、完全に別の関数を作る必要があります。
(まあ、nArray3が増えて、For文の「\ 2」が「\ 3」になるだけですが)

くどいようですが、nString( , )ではなく、nString()()でやることをお勧めします。

> VBのヘルプを調べると、
> 『いわゆる 「多次元」 の配列には、「多次元配列」 と 「多段階配列」 の 2 つがある点です。』

> [例] 多次元配列と多段階配列
> 1: Tbl(3,4) = 100 //多次元配列
> 2: Dat(3)(4) = 200 //多段階配列

その通りです、私が勝手に脳内置換して勘違いしておりました。
しかし、私は多段階の方が便利に感じます。(←くどい)
javaさん、ありがとうございました。

くどいじゃない、親切ですね。

実は、最初の時、「多次元配列」と「多段階配列」の区別もわからないです。恥ずかしいですね。

いまの回答は、実際の仕事とちょっと違います。但し、十分です。
基本的に、ARRAY.SORTを利用して、多次元配列のソートもいけます。

#先ほど、ソートのアルゴリズムを調べて、とても懐かしいです。
#むかしむかし、DOSの時、ソートの関数は全部自分で作りました。
#大抵20年前。。。。。。
解決済み!
■No5908に返信(johnさんの記事)
> 実は、最初の時、「多次元配列」と「多段階配列」の区別もわからないです。恥ずかしいですね。

私の場合は、勝手に脳内置換しておりましたが...
(というより、多次元配列は、使わないことにしておりますので)
申し訳ありません...。

> いまの回答は、実際の仕事とちょっと違います。但し、十分です。
> 基本的に、ARRAY.SORTを利用して、多次元配列のソートもいけます。

そうなのですか?
検索してみたところ、多次元の場合は、一旦配列に移す必要があるみたいなのですが?
配列のコピーもCopy()メソッドを使っても、次元数の扱いがどうしてもダメですし、
展開する際に、(x, y)を、x,y,x,y,x...と展開するのか、
x,x,x,x...y,y,y,y...と展開するかはプログラマ次第となりますし...。
人によって(言語の出身の違いによって)どうしても、みづらいコードになりますので、
そういった意味でも、多段階配列(名前は知らなかった...)を使った方がいいのかな..と。

> #先ほど、ソートのアルゴリズムを調べて、とても懐かしいです。
> #むかしむかし、DOSの時、ソートの関数は全部自分で作りました。
> #大抵20年前。。。。。。

そうですね、私も昔(といっても2, 3年前)CでSortは、
自作関数で、for文を駆使して1個1個手作りでやっていました。

あと、String( , )がどうしても二次元って感じがしません。
というのは、StringはクラスでChar[]として配列で持っていることを考えると、
String( , ) = Char[][][] って感じがするからです。

これも、出身言語による錯覚なのでしょうか...?
解決済み!

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