2010-10-18 116 views
2

我遇到了一个问题,我想创建一个Array表。这是一个2维数组,其中在需要创建表之前,运行时已知行数和列数。所有行的列数都是相同的。如何获取C#中多维数组的单维的引用?

一旦数组被创建,我想操作该数组的1维。也许传递一个方法的参考。

这是一个虚构的例子:

// Create a table 3x3 table. 
int[,] DistanceTable = new int[3, 3]; 
DistanceTable[0, 0] = 0; 
DistanceTable[1, 1] = 0; 
DistanceTable[2, 2] = 0; 

DistanceTable[0, 1] = 10; 
DistanceTable[0, 2] = 40; 

DistanceTable[1, 0] = 10; 
DistanceTable[1, 2] = 25; 

DistanceTable[2, 0] = 40; 
DistanceTable[2, 1] = 25; 

// Why can't I do this? 
int[] twos = DistanceTable[2]; 

如果我使用JaggedArray(数组的阵列),它可以让我做这件事。但是我不需要JaggedArray,因为我的multidemsional数组对于每一行总是有相同数量的列。

可以做到这一点吗?如果不是为什么?

谢谢

+0

你需要一个锯齿状的数组。不要通过Go,不要在没有他们的情况下收取200美元。 – 2010-10-18 23:42:43

回答

3

不是。多维数组不同于Jagged数组,因为它们使用Row-Major ordering按顺序存储在一个内存块中。

因此,拔出一个“列”数据需要跳过才能将其提取出来。

另一方面,锯齿形数组是对第二个数组的引用数组。这可以很容易地从锯齿状阵列中拉出单个“阵列”。

但我不需要JaggedArray,因为我的multidemsional数组总是有相同数量的列为每行。

.NET中的锯齿形数组有一些巨大的性能优化。它们通常胜过多维数组。这就是为什么大多数代码分析例程会建议从二维数组转换为锯齿状数组的原因。即使你不“需要”它也值得考虑。

+0

有趣。我会认为多维数组会更有效率(因此我希望使用它们)。感谢您的好解释!锯齿阵列! – Justin 2010-10-18 23:53:02

+0

@Justin:是的 - 这是非常直观的。 – 2010-10-18 23:54:44

+0

@Justin:Jagged通常更快 - 但**会使用更多的内存。 – 2010-10-18 23:55:15

2

这是不可能的;多维数组不能像那样工作。

一般来说,你应该总是使用锯齿状的数组;他们更快。
(抖动将生成的原始存储器访问指令而不是方法调用)

+2

为什么JITter不能为多维数组做这件事? – 2010-10-19 00:59:53

1

没有与多维数组而交错数组只有一个阵列对象是多个不同阵列对象的嵌套。没有1-1匹配或提取方法(不涉及使用包装)。

0

你可以在你的DictionaryTable对象上做一个扩展方法,允许你指定行吗?

public static class IntArrayExt 
{ 
    public static int[] Row(this int[,] array, int row) 
    { 
     int[] newArray = new int[3]; 
     for (int i = 0; i < array.Length; i++) 
     { 
      newArray[i] = array[row, i]; 
     } 
     return newArray; 
    } 
} 

int[,] distanceTable = new int[3, 3]; 
distanceTable[0, 0] = 0; 
distanceTable[1, 1] = 0; 
distanceTable[2, 2] = 0; 

distanceTable[0, 1] = 10; 
distanceTable[0, 2] = 40; 

distanceTable[1, 0] = 10; 
distanceTable[1, 2] = 25; 

distanceTable[2, 0] = 40; 
distanceTable[2, 1] = 25; 

int[] twos = distanceTable.Row(2); 

如果您想获得一列,您可以制作另一种扩展方法。

1

对不起,这应该是对How do I get a reference to a single dimension of a Multidemensional Array in C#?的评论,但我不能评论。

,反正原因为何性能与交错数组更好的是容易一些解释后明白:让我们来看看多维数组:

{{0,1,2}, {3,4 ,5}, {6,7,8}}

在内存中存储的内容如下所示:{0,1,2,3,4,5,6,7,8}。

现在,假设你想访问[0,0],我们将在内存中读取?我们必须计算地址:y * 3 + x => 0 * 3 + 0 => 0。之后,我们可以继续进行实际读取。如果我们想要阅读整个系列,我们必须一遍又一遍地做这个数学。

相反,看一个交错数组,在存储它的存储是这样的:

一个:{0,1,2} B:{3,4,5} C:{6,7 ,8} {ref:a,ref:b,ref:c}

假设我们想要访问[0] [0],我们要在内存中读取?首先,让我们获得对数组[0]的引用。然后获取单元格[0]的内容。完成。如果我们想要读取整行,我们只需要将指针加1。

如果我们要遍历整个“数组”而不是仅仅一行,它对锯齿状数组仍然具有相同的性能优势。

虽然有一个例外:迭代列。对于参差不齐的数组,这是非常糟糕的,因为我们将为每个访问都执行相对昂贵的内存读取。不好。

如果您觉得这是一个问题,还有一种方法:一维数组!在这种情况下,我们使用多维数组(y * rowLength + x)背后的理论,并使用一些非常简单的数学运算;迭代一行:只增加一个,迭代一列:只增加rowLength。

+0

计算偏移似乎是微不足道的(当然不会比间接查找更昂贵?);我怀疑性能改进是由于更好的缓存命中,特定的优化案例和使用模式,这也可能与这两种方法如何“绘制”常见的迭代模式有关。欢迎来到SO :-) – 2010-10-19 03:03:26

+0

在大多数应用程序中,这是微不足道的,但是,当您在迭代大数组时,性能不佳,那么可以获得性能。但当然,不要过度.. :)谢谢:) – Onkelborg 2010-10-19 09:32:09