多维数组,由向量访问的元素

And*_*ets 4 .net c# arrays multidimensional-array

.Net中是否有任何多维数组/集合/任何数据类型,其中的元素可以通过向量访问(容易改变维数)?像这样(C#):

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

澄清一下:没有必要解释如何手动编写这样的数据类型.

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;
Run Code Online (Sandbox Code Playgroud)

das*_*ght 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

有了这个相等比较器,你可以这样做:

// 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
Run Code Online (Sandbox Code Playgroud)

如果您需要具有特定容量和特定数量的维度,则可以修改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; }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是使用泛型的行主索引方案的直接实现.