为什么我们同时具有锯齿状数组和多维数组?


87
  1. 锯齿状数组和多维数组有什么区别。彼此之间有好处吗?

  2. 为什么Visual Studio不允许我做一个

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

    (我们以前在C ++中这样做,但是在C#中,它用红色的蠕动行强调[20]。表示无效的等级说明符)

    但很满意

    MyClass[,] abc = new MyClass[10,20];
    
  3. 最后,我如何在一行中初始化它(就像我们在的简单数组中所做的那样{new xxx...}{new xxx....}

    MyClass[][,][,] itemscollection;
    

11
锯齿状数组的全部要点是“嵌套”数组不必具有统一的大小。
阿妮

1
msdn.microsoft.com/zh-cn/library/2yd9wwz4(v=vs.71).aspx-根据文档,多维数组语法为[X,Y]有效
ndtreviv 2011年

附加的子问题:是否可以将foreach()与多维数组一起使用?
Serge Wautier 2011年

@Serge-当然是Array工具IEnumerable。您可以随时尝试一下,看看自己:)
thecoop 2011年

Answers:


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. MyClass[][,][,]可以这样初始化A (尽管未进行编译测试):

    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


多维数组有(通用)用例吗?
ryanwebjackson

1
示例:棋盘格var board = new Piece[8, 8];转换矩阵 var m = new double[2, 2];
奥利维尔·雅各布·德斯科姆斯

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

我知道这已经很老了,但仅出于信息目的int [3]是不必要的。一个简单的int []就很重要。int [] [] myArray = new int [5] []; myArray [0] = new int [] {1,2,3,4}; 这就是所有必要的事情。
Velocibadgery

你能用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

对于#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数组。就像C ++中的这段代码一样,

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

下面的代码的内存分配与C#中的2d锯齿状数组相同。但是我对此表示怀疑,如果我以错误的方式想请您解释一下。


0

这篇文章很旧,但是我对此有何看法。

锯齿状数组是多维数组。多维数组有两种:矩形和锯齿状。矩形数组代表内存的n维块,锯齿状数组是数组的数组。

矩形阵列

矩形数组使用逗号分隔每个维。下面的语句声明一个矩形二维数组,其尺寸为3×3:

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

锯齿状阵列

锯齿状数组使用连续的方括号表示每个维来声明。这是声明一个锯齿状二维数组的示例,其中最外面的维是:3:

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

0

对于多维数组,请考虑一个盒子或矩形。每行长度相同,每列长度相同。

在锯齿状数组中,行和列的大小可能不相同。例如,列或行可以是不同的大小。这将导致形状可能不是矩形下方的直线。相反,侧面可能呈锯齿状

现在,在此示例中,我使用了2维/ 2个数组,但这适用于更多示例。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.