为啥我们既有交错数组又有多维数组?

Posted

技术标签:

【中文标题】为啥我们既有交错数组又有多维数组?【英文标题】:Why we have both jagged array and multidimensional array?为什么我们既有交错数组又有多维数组? 【发布时间】:2011-06-06 15:24:29 【问题描述】:

    交错数组和多维数组有什么区别。 彼此之间有好处吗?

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

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

    (我们曾经在 C++ 中这样做,但在 C# 中,它用红色蠕动线在 [20] 下划线。表示无效的排名说明符)

    但是很满意

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

    最后我怎样才能在一行中初始化它(就像我们在简单的数组中用new xxx...new xxx.... 做的那样)

    MyClass[][,][,] itemscollection;
    

【问题讨论】:

锯齿状数组的全部意义在于“嵌套”数组不必具有统一的大小。 msdn.microsoft.com/en-us/library/2yd9wwz4(v=vs.71).aspx - 根据文档,多维数组语法为 [X,Y] 是有效的 附加子问题:是否可以将 foreach() 与多维数组一起使用? @Serge - 当然,因为Array 实现了IEnumerable。您可以随时尝试并亲自查看:) What is differences between Multidimensional array and Array of Arrays in C#?的可能重复 【参考方案1】:

    锯齿状数组是数组的数组,所以int[][]int[] 的数组,每个数组可以有不同的长度并在内存中占用自己的块。多维数组 (int[,]) 是单个内存块(本质上是一个矩阵)。

    您不能创建MyClass[10][20],因为每个子数组必须单独初始化,因为它们是单独的对象:

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

    MyClass[10,20] 可以,因为它将单个对象初始化为 10 行 20 列的矩阵。

    MyClass[][,][,] 可以这样初始化(虽然没有经过编译测试):

    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 针对单维数组访问进行了大量优化,因此使用锯齿状数组可能比相同大小的多维数组更快。

【讨论】:

你能指出一些单维数组访问速度更快的证据吗? @GreyCloud - ***.com/questions/597720/… 多维数组有(常见)用例吗? 例子:棋盘var board = new Piece[8, 8];,transformation matrixvar m = new double[2, 2];【参考方案2】:

锯齿状数组是数组的数组。不保证每个数组的大小相同。你可以有

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 ; 我知道这是旧的,但只是为了提供信息 int[3] 是不必要的。一个简单的 int[] 才是最重要的。 int[][] myArray = new int[5][]; myArray[0] = new int[] 1, 2, 3, 4;这就是所有必要的。 你能用 C# 编译它吗?我无法编译jaggedArray[0] = 1, 2, 3 ;,除非我将其更改为= new[] 1, 2, 3 (或C# 3.0 之前的= new int[] 1, 2, 3 )。根据微软的C# Programming Guide,“你可以声明一个数组变量而不创建它,但是你在给这个变量分配一个新数组时必须使用new操作符。”【参考方案3】:

矩形数组的每一行总是有相同数量的列。

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)];

This 对你来说可能是一篇有趣的文章。

【讨论】:

【参考方案4】:

广告 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 ;

【讨论】:

【参考方案5】:

如果您正在寻找已设置边界的多维数组,请始终使用[,] 样式语法。这将确保每个部分的大小相同。

当您使用[][] 时,实际情况是您正在创建一个数组数组。这意味着每个数组的大小可以不同。例如:

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

    jaggedArray[index] = new int[index + 1];

【讨论】:

【参考方案6】:

内联声明看起来像这样:

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

【讨论】:

【参考方案7】:

对于#1,请参阅this SO question

对于锯齿状或多维内联数组,请参阅programming guide:

// 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) 会很有帮助。

【讨论】:

【参考方案8】:

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

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

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

【讨论】:

【参考方案9】:

您需要了解数组的内部工作原理 多维数组作为一维数组,除了双索引转换为单索引。

您在 c# 中的 Jagged 数组是一个对象数组,这些对象依次是数组。

【讨论】:

【参考方案10】:

我认为 C# 中的二维锯齿状数组内存分配类似于 C++ 和 C 中的二维数组。 因为 2d 锯齿状数组具有指向指针数组的指针,每个指针都指向一个元素数组(例如整数元素);就像这段 C++ 代码,

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

   2DArr[i] = new int[number2];

下面代码的内存分配与 C# 中的二维锯齿数组相同。但我对此表示怀疑,如果我的想法有误,请您解释一下。

【讨论】:

【参考方案11】:

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

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

矩形数组

矩形数组使用逗号分隔每个维度。以下语句声明了一个矩形二维数组,其中维度为 3 × 3:

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

锯齿状数组

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

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

【讨论】:

【参考方案12】:
 public class ArrayExamples    

            //Multi-Dimensional Array are of 2 types
            //1. Jagged Array: Array of Arrays
            //2. rectangular Array: Array having more than one dimension
            public void JaggedArray()
            
                //Declaring an array with 3 element. Each element containing single dimension array.
                //Benefit: Each single dimension array defined can be of different length.
                int[][] jaggedArray = new int[3][];
    
                jaggedArray[0] = new int[]  1, 2, 3, 4, 5 ;//single dimension array lengh:5
                jaggedArray[1] = new int[]  6,7,8;//single dimension array lengh:3
                jaggedArray[2] = new int[]  9, 10 ;//single dimension array lengh:2
    
                foreach (var array in jaggedArray)
                    foreach (var element in array)
                    
                        Console.WriteLine(element);
                    
            
    
    
            public void RectangularArray()
             
                //Declaring a 2 dimensional array with  5 rows and 2 columns.
                //Benefits: When we want to declare an array with multiple dimension
                //and we know the length as length should be predefined.
                //
    
                int[,] array2Dimensional = new int[5,2]   1, 2 ,  3, 4 ,  5, 6 ,  7, 8 ,  9, 10  ;
    
    
                //This loop will go through all the elements
                //This will display all the elements i.e. 1,2,3,4,5,6,7,8,9,10
                foreach (var element in array2Dimensional)
                
                   //Console.WriteLine(element);
                
    
                //Accessing specific element in the 2 dimensional array.
                //i.e. will display 1 which is the first element of first row and first column.
                Console.WriteLine(array2Dimensional[0, 0]);
            
        

【讨论】:

【参考方案13】:

多维数组是 C# 中的矩形数组。它在每个维度中只能有固定数量的元素。下面的代码示例向我们展示了如何在 C# 中声明多维数组。

int[,] multiArray = new[3,3]

交错数组是 C# 中的数组数组。它可以在其中构成不同大小的数组。下面的代码示例向我们展示了如何在 C# 中声明一个锯齿状数组。

int[][] jaggedArray = new int[3][];
            jaggedArray[0] = new int [1];
            jaggedArray[1] = new int[2];
            jaggedArray[2] = new int[3];

在上面的代码中,我们创建了大小为 3 的锯齿状数组 jaggedArray,也就是说这个 jaggedArray 是一个由 3 个数组组成的数组。这 3 个数组位于 jaggedArray 的索引 0、1 和 2 处。从示例中可以清楚地看出,所有这些数组的大小都不同。

锯齿状数组应该优于传统的多维数组,因为它们在 C# 中具有灵活性。例如,如果我们必须存储一个人的爱好,首选的方法是使用锯齿状数组,因为不是每个人都有相同数量的爱好。兴趣和许多其他事情也是如此。

【讨论】:

以上是关于为啥我们既有交错数组又有多维数组?的主要内容,如果未能解决你的问题,请参考以下文章

c# 多维数组交错数组(转化为DataTable)

多维数组与交错数组的转换

为啥 Java 没有真正的多维数组?

为啥扩展元素不适合复制多维数组?

为啥扩展元素不适合复制多维数组?

多维动态数组,为啥不起作用?