如何在CSharp中实现多维数组改组?

时间:2018-08-20 12:45:42

标签: c# .net arrays multidimensional-array

我想知道是否有可能在C#中实现通用的Julia \ Matlab类似的View函数,使其像任何尺寸的数组(例如[,,][,,,])一样工作它在array slicer\mover view中。所以我想知道是否有一个库可以为CSharp多维数组提供类似的功能,或者如何在C#中实现它?

1 个答案:

答案 0 :(得分:2)

解决方案有两个:

  1. 使用包装类来保存对主数组的引用
  2. 使用Array基类使其具有多态性

包装

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

二维示例

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示例

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