2013-04-26 142 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