tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルジャグ配列でRedim Preserve みたいな使い方をしたいのです
記事No11892
投稿日: 2017/08/31(Thu) 15:26
投稿者Nis9036
毎々お世話になります。
例えば、2〜10までの数のそれぞれの公約数をリストアップしたい。その為にジャグ配列を使いたいのですが、Redim Preserve の様に使う事は出来ませんか?
        Dim Yak(2)() As Integer     '2〜10の数のそれぞれの配列を格納する
        Dim Temp() As Integer       '仮の配列
        Dim N1, N2, N3 As Integer

        For N1 = 2 To 10            '2〜10の配列をジョグ配列に格納する
            ReDim Temp(0)
            N3 = 0
            For N2 = 1 To N1 / 2
                If N1 Mod N2 = 0 Then
                    ReDim Preserve Temp(N3)     '仮の約数配列に登録
                    Temp(N3) = N2
                    N3 = N3 + 1
                End If
            Next
            Yak(N1) = New Integer() {}
            For N2 = 0 To Temp.Length - 1
                Yak(N1)(N2) = Temp(N2)      'ここで仮の配列からジャグ配列に値を移したい
            Next
        Next
        MsgBox("End")
    End Sub

とやってみると下から3行目の Yak(N1)(N2) = Temp(N2) 所で、「データ列名が適切である事を確認します」とストップしてしまいます。
本当は Redim Preserve の様に使いたいのですが、どうやれば出来るのか分かりませんでした。
2〜10までの約数だけなら中括弧{}の中に値を入れていけば済みますが、多くなってくるとそうも行きません。
宜しく教えて下さい。

[ツリー表示へ]
タイトルRe: ジャグ配列でRedim Preserve みたいな使い方をしたいのです
記事No11894
投稿日: 2017/08/31(Thu) 15:58
投稿者Hongliang
単純に、
Yak(N1) = Temp
だけでもいいんじゃないかと思いますけど。

Tempは、約数の探索時には、動的に要素が追加されていくという性質を持っていますよね。
こういう場合、配列を追加のたびにReDim Preserveしていくのではなく、
配列の代わりにList(Of Integer)を使います。
そうすれば、追加時にAddしていくだけで済みます。

For N1 As Integer = 2 To 10            '2〜10の配列をジャグ配列に格納する
    Dim Temp As New List(Of Integer) ' 変数はメソッド先頭で全部宣言するより必要なところで宣言したほうが見やすい
    For N2 As Integer = 1 To N1 / 2
        If N1 Mod N2 = 0 Then
            Temp.Add(N2)
        End If
    Next
    ReDim Preserve Yak(N1) ' Yakの要素数を確保
    Yak(N1) = Temp.ToArray() ' 最終的に配列にするにはToArrayメソッド
Next

また、Yakも、毎回ReDim Preserveするのは非効率です。
上限が10と決まっているのであれば初めにDimする際に
Dim overLimit = 10 ' 実際にはメソッド引数とかで渡されるとか?
Dim Yak(overLimit)()
のようにすればいちいちReDim Preserveする必要はなくなります。
// 個人的には、ジャグ配列ではなく、Dictionary(Of Integer, Integer())を使いたいところですが。

[ツリー表示へ]
タイトルRe^2: ジャグ配列でRedim Preserve みたいな使い方を
記事No11896
投稿日: 2017/08/31(Thu) 16:24
投稿者Nis9036
Hongliang 様

ありがとうございました。
ジョグ配列は初めてだったので直ぐに教えて貰えて助かりました。
又、Dictionary(Integer, Of Integer())と云うメソッドも便利そうだと言う事なのでそっちの方も調べてみる事にします。

[ツリー表示へ]
タイトルRe: ジャグ配列でRedim Preserve みたいな使い方をしたいのです
記事No11895
投稿日: 2017/08/31(Thu) 16:16
投稿者魔界の仮面弁士
> 例えば、2〜10までの数のそれぞれの公約数をリストアップしたい。

2〜10、すなわち「2 と 3 と 4 と 5 と 6 と 7 と 8 と 9 と 10」
に対する公約数は「1」しか無いと思いますが、それを調べるために、
まずは約数を得たいということでしょうか。
(連続数に対する公約数なら、ほとんどの場合「1」しか残らない気もしますが)


ひとまず約数の列挙ということであれば、

Dim 約数1 = Enumerable.Range(2, 9).ToDictionary(
                Function(a) a,
                Function(b) Enumerable.Range(1, b).Where(
                    Function(c) b Mod c = 0
                ).ToArray()
            )

によって、下記と同じ結果が得られます。

Dim 約数2 As New Dictionary(Of Integer, Integer()) From {
  { 2, { 1, 2 } },
  { 3, { 1, 3 } },
  { 4, { 1, 2, 4 } },
  { 5, { 1, 5 } },
  { 6, { 1, 2, 3, 6 } },
  { 7, { 1, 7 } },
  { 8, { 1, 2, 4, 8 } },
  { 9, { 1, 3, 9 } },
  { 10,{ 1, 2, 5, 10 } }
}



> Dim Yak(2)() As Integer     '2〜10の数のそれぞれの配列を格納する
> 2〜10までの約数だけなら中括弧{}の中に値を入れていけば済みますが、多くなってくるとそうも行きません。

どういう結果が入ってほしいのかイメージできなかったので、実際に得たい結果を
 Yak(0) = New Integer() {…}
 Yak(1) = New Integer() {…}
 Yak(2) = New Integer() {…}
の形式で列挙してみていただけないでしょうか。

[ツリー表示へ]
タイトルRe^2: ジャグ配列でRedim Preserve みたいな使い方をしたいのです
記事No11897
投稿日: 2017/08/31(Thu) 16:35
投稿者Nis9036
魔界の弁士様

> > 例えば、2〜10までの数のそれぞれの公約数をリストアップしたい。

書き間違いでした。キーボードを叩く指が 約数 と書く所を つい使う事の多い 公約数と書いてしまいました。

Dictionary メソッド(で良いのでしょうか?)についてはHongLinang様からも指摘を受けましたから、後で調べてみるつもりです。
日本を離れて、手許にテキストが無い状況ではここの掲示板は本当に助かります。
ありがとうございました。

[ツリー表示へ]
タイトルRe^3: ジャグ配列でRedim Preserve みたいな使い方をしたいのです
記事No11898
投稿日: 2017/08/31(Thu) 17:52
投稿者魔界の仮面弁士
> 魔界の弁士様
×魔界の弁士
○魔界の仮面弁士

> HongLinang様からも
×HongLinang
○Hongliang


> Dictionary メソッド(で良いのでしょうか?)

「Dictionary クラス」ですね。型パラメーターまで含めて書くとこんな感じ。

Dim 約数1 As Dictionary(Of Integer, Integer())


また、先のコードの .ToDictionary は、
戻り値として Dictionary を返す「拡張メソッド」です。


結果を見るときは、このようにします。

MsgBox( 約数1(2).Length ) '2 を返す … 2 の約数は、{1, 2} の 2 つ
MsgBox( 約数1(8).Length ) '4 を返す … 8 の約数は、{1, 2, 4, 8} の 4 つ
MsgBox( 約数1(8)(0) ) '1 を返す
MsgBox( 約数1(8)(1) ) '2 を返す
MsgBox( 約数1(8)(2) ) '4 を返す
MsgBox( 約数1(8)(3) ) '8 を返す


元質問の Jagged Array として受け取る例も記載しておきます。
冒頭の「Dim Yak(2)() As Integer」の意図に合っているのかは不明ですが。


Dim 約数3()() As Integer = Enumerable.Range(2, 9).Select(
   Function(b) Enumerable.Range(1, b).Where(
    Function(c) b Mod c = 0
  ).ToArray()
 ).ToArray()


この場合、
 MsgBox( 約数3(0).Length ) '2 を返す … 2 の約数は、{1, 2} の 2 つ
 MsgBox( 約数3(2).Length ) '2 を返す … 4 の約数は、{1, 2, 4} の 3 つ
 MsgBox( 約数3(8).Length ) '4 を返す … 10 の約数は、{1, 2, 5, 10} の 4 つ
という形になります。

「10 の約数」が、ジャグ配列の「約数3(8)」に格納されているよりも、
「10 の約数」が、Dictionaryの「約数1(10)」に格納されている方が分かりやすいですよね。

[ツリー表示へ]