2013-04-26 88 views
4

是否有任何多維數組/集合/無論.Net中的數據類型,其中的元素可以通過矢量訪問(以輕鬆改變維數)?像這樣(C#):多維數組,元素訪問矢量

var array = new Smth<double>(capacity: new int[] {xCap, yCap, zCap}); 
array[new int[] {x, y, z}] = 10.0; 

澄清:沒有必要解釋我該如何手動編寫這樣的數據類型。

Upodate:

我的意思是不同的以前創作,而不是之後。

// 3D array 
var array = new Smth<double>(capacity: new int[] {xCap, yCap, zCap}); 
array[new int[] {x, y, z}] = 10.0; 

// 6D array 
var array = new Smth<double>(capacity: new int[] {xCap, yCap, zCap, tCap, vCap, mCap}); 
array[new int[] {x, y, z, t, v, m}] = 10.0; 
+0

你知道編譯時的維數嗎?我假設答案是「不」,對吧? – dasblinkenlight 2013-04-26 18:17:47

+0

當您查看時,您是否知道維度的數量?你能提供一個不同維度的例子嗎? – Bobson 2013-04-26 18:23:16

回答

6

雖然沒有像現成的架子集合,您可以輕鬆地將它們用Dictionary<int[],double>和定製IEqualityComparerer<int[]>,像這樣的模擬:

class ArrayEq : IEqualityComparerer<int[]> { 
    public bool Equals(int[] a, int[] b) { 
     return a.SequenceEquals(b); 
    } 
    public int GetHashCode(int[] a) { 
     return a.Aggregate(0, (p, v) => 31*p + v); 
    } 
} 

有了這個相等比較器在手,你可以這樣做:

// The number of dimensions does not matter: if you pass a different number 
// of dimensions, nothing bad is going to happen. 
IDictionary<int[],double> array = new Dictionary<int[],double>(new ArrayEq()); 
array[new[] {1,2,3}] = 4.567; 
array[new[] {1,2,-3}] = 7.654; // Negative indexes are OK 
double x = array[new[] {1,2,3}]; // Get 4.567 back 

如果你需要有一定的容量和尺寸的具體數量,你可以修改ArrayEq要更嚴格地驗證數據。

如果您知道編譯時的維數,您可以使用Tuple<...>類之一來代替數組,以獲得更好的性能。你也可以在多維上定義擴展方法,比如說,double[,,,],數組,來獲取索引的向量。儘管這兩種方法都不能提供相同的靈活性(這是一種常見的折衷 - 通過降低靈活性往往可以獲得更好的性能)。

編輯:如果您需要預先分配存儲,避免存儲您的索引,你可以實現一個多維數組自己 - 這樣的:

class MultiD<T> { 
    private readonly T[] data; 
    private readonly int[] mul; 
    public MultiD(int[] dim) { 
     // Add some validation here: 
     // - Make sure dim has at least one dimension 
     // - Make sure that all dim's elements are positive 
     var size = dim.Aggregate(1, (p, v) => p * v); 
     data = new T[size]; 
     mul = new int[dim.Length]; 
     mul[0] = 1; 
     for (int i = 1; i < mul.Length; i++) { 
      mul[i] = mul[i - 1] * dim[i - 1]; 
     } 
    } 
    private int GetIndex(IEnumerable<int> ind) { 
     return ind.Zip(mul, (a, b) => a*b).Sum(); 
    } 
    public T this[int[] index] { 
     get { return data[GetIndex(index)]; } 
     set { data[GetIndex(index)] = value; } 
    } 
} 

這是一個簡單的實現行 - 使用泛型的主要索引方案。

+0

它看起來像我需要的,但我也希望在創建時分配整個數組內存,我不希望這些索引被存儲(所以它更像是數組或列表而不是字典)。可能嗎? – 2013-04-26 18:38:26

+0

咦?如果你不想存儲它們,爲什麼要使用它們呢? – Bobson 2013-04-26 18:42:04

+0

@ andriy.kashchynets如果你想預先分配存儲並避免存儲索引,你需要一種不同的方法(編輯)。 – dasblinkenlight 2013-04-26 18:45:09