2010-10-18 84 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