DuckQueen
DuckQueen

Reputation: 810

How to implement a multidimensional array shuffling in CSharp?

I wonder if it is possible to implement a general Julia\Matlab alike View function in C# that would work for arrays of any dimensions (eg [,,] and [,,,]) as they do it in array slicer\mover view. So I wonder if there is a library that provides similar functionality for CSharp multidimentional arrays or how to implement it in C#?

Upvotes: 0

Views: 59

Answers (1)

ingen
ingen

Reputation: 1189

The solution is twofold:

  1. Use a wrapper class that holds a reference to the master array
  2. Use the Array base class to make it polymorphic

Wrapper

class View<T>
{
    private readonly Array array;
    private readonly int dim;
    private readonly int slice;

    public View(Array array, int dim, int slice)
    {
        this.array = array;
        this.dim = dim;
        this.slice = slice;
    }

    public T this[params int[] indexes]
    {
        get { return (T)array.GetValue(BaseIndexesFor(indexes)); }
        set { array.SetValue(value, BaseIndexesFor(indexes)); }
    }

    private int[] BaseIndexesFor(int[] indexes)
    {
        if (indexes.Length != array.Rank - 1) throw new ArgumentException("indexes");

        int i_index = 0;
        int[] baseIndexes = new int[array.Rank];

        for (int i = 0; i < baseIndexes.Length; i++)
        {
            baseIndexes[i] = (i == dim) ? slice : indexes[i_index++];
        }

        return baseIndexes;
    }
}

2D example

var A = new int[,]
{
    { 1, 2, 3 },
    { 4, 5, 6 },
    { 7, 8, 9 }
};

/* View(Array array, int dim, int slice)
 * 
 * For 2 dimensional array:
 * dim=0 -> rows
 * dim=1 -> columns
*/
// From second dimension slice index 1
// Or simply, take column with index 1
var B = new View<int>(A, 1, 1); 

B[2] = 0;
Console.WriteLine(A[2, 1]); // 0

3D examples

var C = new int[,,]
{
    { 
        { 1, 2, 3 },
        { 4, 5, 6 },
        { 7, 8, 9 }
    },
    {
        { 11, 12, 13 },
        { 14, 15, 16 },
        { 17, 18, 19 }
    },
    {
        { 21, 22, 23 },
        { 24, 25, 26 },
        { 27, 28, 29 }
    }
};

/* From first dimension slice index 2
 * { 21, 22, 23 },
 * { 24, 25, 26 },
 * { 27, 28, 29 }
 */
var D = new View<int>(C, 0, 2);

D[1, 1] = 0;
Console.WriteLine(C[2, 1, 1]); // 0

/* From third dimension slice index 0
 * { 1, 4, 7 },
 * { 11, 14, 17 },
 * { 21, 24, 27 }
 */
var E = new View<int>(C, 2, 0);

E[2, 0] = 0;
Console.WriteLine(C[2, 0, 0]); // 0

Upvotes: 2

Related Questions