Multidimensional array, elements accessed by the vector

Is there any multidimensional array / collection / any data type in .NET whose elements can be accessed using a vector (to easily vary the number of dimensions)? Like this (C #):

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

To clarify: there is no need to explain how I can write this type of data manually.

Upodate:

I mean the change before , not after.

 // 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; 
+4
source share
1 answer

Despite the lack of ready-made collections, you can easily simulate them using Dictionary<int[],double> and custom IEqualityComparerer<int[]> , for example:

 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); } } 

With this equality mapping, you can do this:

 // 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 

If you need a certain capacity and a certain number of measurements, you can change ArrayEq to be more strict when checking data.

If you knew the number of dimensions at compile time, you could use one of the Tuple<...> classes instead of arrays for potentially better performance. You can also define extension methods for multidimensional, say, double[,,,] arrays to take index vectors. However, neither of these two approaches provides the same flexibility (which is a common compromise - higher performance can often be achieved by reducing flexibility).

EDIT: If you need to pre-allocate storage and not store your indexes, you can implement a multidimensional array yourself - for example:

 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 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; } } } 

This is a simple implementation of a row indexing scheme that uses generics.

+6
source

All Articles