ギザギザの配列と多次元配列の両方があるのはなぜですか?


87
  1. ギザギザの配列と多次元配列の違いは何ですか。お互いにメリットはありますか?

  2. そして、なぜVisualStudioでは許可されないのでしょうか。

    MyClass[][] abc = new MyClass[10][20];
    

    (以前はC ++でこれを行っていましたが、C#では[20]に赤いしわくちゃの線で下線が引かれています。無効なランク指定子と表示されます)

    でも満足しています

    MyClass[,] abc = new MyClass[10,20];
    
  3. 最後に、これを1行で初期化するにはどうすればよいですか(単純な配列で行うように{new xxx...}{new xxx....}

    MyClass[][,][,] itemscollection;
    

11
ギザギザの配列の要点は、「ネストされた」配列が均一なサイズである必要がないということです。
アニ2011年

1
msdn.microsoft.com/en-us/library/2yd9wwz4(v=vs.71).aspx-[X、Y ]としての多次元配列構文は、ドキュメントに従って有効です
ndtreviv 2011年

追加のサブ質問:多次元配列でforeach()を使用することは可能ですか?
Serge Wautier 2011年

@ Serge-もちろん、Array実装としてIEnumerable。あなたはいつでもそれを試して自分の目で確かめることができます:)
thecoop 2011年

回答:


101
  1. ギザギザの配列は配列の配列であるため、int[][]はの配列でありint[]、それぞれの長さを変えて、メモリ内の独自のブロックを占有することができます。多次元配列(int[,])は、単一のメモリブロック(基本的には行列)です。

  2. MyClass[10][20]各サブ配列は個別のオブジェクトであるため、個別に初期化する必要があるため、を作成することはできません。

    MyClass[][] abc = new MyClass[10][];
    
    for (int i=0; i<abc.Length; i++) {
        abc[i] = new MyClass[20];
    }
    

    AMyClass[10,20]は、単一のオブジェクトを10行20列の行列として初期化しているため問題ありません。

  3. AMyClass[][,][,]はそのように初期化できます(ただし、コンパイルテストは行われません):

    MyClass[][,][,] abc = new MyClass[10][,][,];
    
    for (int i=0; i<abc.Length; i++) {
        abc[i] = new MyClass[20,30][,];
    
        for (int j=0; j<abc[i].GetLength(0); j++) {
            for (int k=0; k<abc[i].GetLength(1); k++) {
                abc[i][j,k] = new MyClass[40,50];
            }
        }
    }
    

CLRは単一次元の配列アクセス用に大幅に最適化されているため、ギザギザの配列を使用すると、同じサイズの多次元配列よりも高速になる可能性があることに注意してください。


6
一次元配列アクセスがより高速であるといういくつかの証拠を指摘できますか?
GreyCloud 2011年


多次元配列の(一般的な)ユースケースはありますか?
ryanwebjackson 2017年

1
例:市松模様のボードvar board = new Piece[8, 8];変換行列 var m = new double[2, 2];
OlivierJacot-Descombes19年

37

ギザギザの配列は、配列の配列です。各アレイが同じサイズであるとは限りません。あなたが持つことができます

int[][] jaggedArray = new int[5][];
jaggedArray[0] = new[] {1, 2, 3}; // 3 item array
jaggedArray[1] = new int[10];     // 10 item array
// etc.

これは、関連する配列のセットです。

一方、多次元配列は、ボックス、テーブル、立方体などのように、不規則な長さがない、よりまとまりのあるグループです。つまり、

int i = array[1,10];
int j = array[2,10]; // 10 will be available at 2 if available at 1

私はあなたのコードを試しました。コンパイルされませんでした。int [3]を追加してみてくださいjaggedArray[0] = int[3]{ 1, 2, 3 }
barlop 2016

これは古いことは知っていますが、情報提供のみを目的としたint [3]は必要ありません。重要なのは単純なint []だけです。int [] [] myArray = new int [5] []; myArray [0] = new int [] {1、2、3、4}; 必要なのはこれだけです。
Velocibadgery 2018

これをC#でコンパイルできますか?にjaggedArray[0] = { 1, 2, 3 };変更しないと= new[] { 1, 2, 3 }(または= new int[] { 1, 2, 3 }C#3.0より前に)コンパイルできません。MicrosoftのC#プログラミングガイドによると、「配列変数は作成せずに宣言できますが、この変数に新しい配列を割り当てるときは、new演算子を使用する必要があります。」
Joel V. Earnest-DeYoung

11

長方形配列には、すべての行に対して常に同じ数の列があります。

MyClass[,] x = new MyClass[10,30]

すべての行には30列がありますが、ギザギザの配列では、これは必須ではありません。したがって、ギザギザの配列のすべての「行」を個別に初期化する必要があると思います。

MyClass[][] x = new MyClass[10][];

for(int i = 0; i < 10; i++)
{
    x[i] = new MyClass[30];
}

実際、これは、ギザギザの配列のすべての行に同じ数の要素が含まれている必要があるわけではないことを意味します。(私の例では、同じ数の要素がありますが、これは必須ではありません)。

たとえば、これを完全に行うことができます。

MyClass[][] x = new MyClass[10][];

for(int i = 0; i < 10; i++)
{
    x[i] = new MyClass[(30 + i)];
}

これはあなたにとって興味深い記事かもしれません。


5

広告3)のようなモンスターを初期化[][,][,]するには、次のようなことができます。

        int [,][,] multiArr1 = { { new int[,] { { 2, 2 }, { 1, 1 } },
                                     new int[,] { { 2, 2 }, { 1, 1 } } },
                                     { new int[,] { { 2, 2 }, { 1, 1 } },
                                         new int[,] { { 2, 2 }, { 1, 1 } } } };
        int [,][,] multiArr2 = { { new int[,] { { 2, 2 }, { 1, 1 } },
                                     new int[,] { { 2, 2 }, { 1, 1 } } },
                                     { new int[,] { { 2, 2 }, { 1, 1 } },
                                         new int[,] { { 2, 2 }, { 1, 1 } } } };

        int [][,][,] superMultiArray = { multiArr1, multiArr2 };

1

境界が設定されている多次元配列を探している場合は、常に[,]スタイル構文を使用してください。これにより、各部分のサイズが等しくなります。

[][]実際に行っていることを使用すると、配列の配列を作成していることになります。これは、各アレイのサイズを変えることができることを意味します。例えば:

int[][] jaggedArray = new int[5][]
for(int index = 0; index < jaggedArray.Length ; ++index)
{
    jaggedArray[index] = new int[index + 1];
}

1

インライン宣言は次のようになります。

int[,] numbers = { {1, 2}, {3, 4}, {5, 6} };

1

#1については、このSOの質問を参照してください

ギザギザまたは多次元のインライン配列については、次のプログラミングガイドを参照してください

// Three-dimensional array.
int[, ,] array3D = new int[,,] { { { 1, 2, 3 }, { 4, 5, 6 } },
{ { 7, 8, 9 }, { 10, 11, 12 } } };

// Same array with dimensions specified at declaration.
int[, ,] array3Da = new int[2, 2, 3] { { { 1, 2, 3 }, { 4, 5, 6 } },
{ { 7, 8, 9 }, { 10, 11, 12 } } };

寸法(array3D)を指定する必要はありませんが、寸法が変更されないことがわかっている場合は、使用している寸法(array3Da)を知っておくと役立ちます。


0

配列の内部動作を理解する必要があります。ただし、二重インデックスが単一のインデックスに変換されることを除いて、多次元配列は単一次元配列として機能します。

C#のギザギザの配列は、順番に配列になっているオブジェクトの配列です。


0

C#での2dギザギザ配列のメモリ割り当ては、C ++およびCでの2d配列に似ていると思います。2Dギザギザ配列には、各ポインタが要素の配列(たとえば整数要素)を指すポインタの配列を指すポインタがあるためです。C ++のこのコードのように、

int** 2DArr {new int* [number1]};
for (int i = 0; i < number1; i++)
{
   2DArr[i] = new int[number2];
}

以下のコードのメモリ割り当ては、C#の2Dギザギザ配列と同じです。しかし、私は疑わしいです、私が間違った方法で考えるならば、あなたはもっと説明してもらえますか?


0

この投稿は古いですが、これが私の考えです。

ギザギザの配列は多次元配列です。多次元配列には、長方形とギザギザの2種類があります。長方形の配列はメモリのn次元ブロックを表し、ギザギザの配列は配列の配列です。

長方形配列

長方形配列は、各次元を区切るためにコンマを使用して宣言されます。次のステートメントは、長方形の2次元配列を宣言します。ここで、次元は3×3です。

int[,] matrix = new int [3, 3]; 

ギザギザの配列

ギザギザの配列は、各次元を表すために連続する角括弧を使用して宣言されます。これは、ギザギザの2次元配列を宣言する例です。ここで、最も外側の次元は3です。

int[][] matrix = new int[3][];

0

多次元配列の場合、ボックスまたは長方形を考えてください。各行は同じ長さであり、各列は同じ長さです。

ギザギザの配列では、行と列のサイズが同じでない場合があります。たとえば、列または行のサイズが異なる場合があります。これは、長方形のように側面を下る直線ではない可能性のある形状につながります。代わりに、側面がギザギザになる場合があります。

この例では2次元/ 2配列を使用しましたが、これはさらに多くの場合に当てはまります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.