如何获得3维数组的横截面c#

时间:2017-04-07 07:40:13

标签: c# arrays multidimensional-array

假设你在c#

中有一个三维数组
al="  c  "
echo -n "|${val}"
val="${val##+( )}"
val="${val%%+( )}"
echo "|${val}|"

你想实现方法

int space[width, height, depth];

其中'position'是指定要提取切片的'尺寸'的点。重要的是使用我们只处理3个维度的事实,在下面的示例中,您可以通过添加if语句来修复它们,并假设矩阵不会超过3维。

我的第一次尝试(评论问题区域):

public int[,] GetCrossSection(int position, int dimension)

我的第二次尝试,同样徒劳无功:

public int[,] GetCrossSection(int position, int dimension)
{
    int[] dimensionIterationInterval = new int[] { width, height, depth };
    var dims = new List<int>(dimensionIterationInterval);
    dims.RemoveAt(dimension);
    dimensionIterationInterval = dims.ToArray();


    int[,] crossSection = new int[dimensionIterationInterval[0], dimensionIterationInterval[1]];
    int[] itr = new int[2];
    for (itr[0] = 0; itr[0] < dimensionIterationInterval[0]; itr[0]++)
    {
        for (itr[1] = 0; itr[1] < dimensionIterationInterval[1]; itr[1]++)
        {
           crossSection[itr[0], itr[1]] = space[?,?,?]; //Problem
        }
     }
}

这两种尝试都陷入了死胡同。你会如何解决它?对于空间维数[,,]具有固定的迭代循环是可以的。如果维度的数量增长有点可管理。聪明/有限,如果法规可以起作用,但每个维度的ifs不会过多。

3 个答案:

答案 0 :(得分:2)

快速草稿:

    static int[,] GetSlice(int[,,] source, int dimension, int position)
    {
        int l1 = 0, l2 = 0;
        if (dimension == 0)
        {
            l1 = source.GetLength(1);
            l2 = source.GetLength(2);
        }
        else if (dimension == 1)
        {
            l1 = source.GetLength(0);
            l2 = source.GetLength(2);
        }
        else if (dimension == 2)
        {
            l1 = source.GetLength(0);
            l2 = source.GetLength(1);
        }

        var result = new int[l1, l2];

        var s0 = dimension == 0 ? position : 0;
        var s1 = dimension == 1 ? position : 0;
        var s2 = dimension == 2 ? position : 0;

        var m0 = dimension == 0 ? position + 1 : source.GetLength(0);
        var m1 = dimension == 1 ? position + 1 : source.GetLength(1);
        var m2 = dimension == 2 ? position + 1 : source.GetLength(2);

        for (var i0 = s0; i0 < m0; i0++)
        for (var i1 = s1; i1 < m1; i1++)
        for (var i2 = s2; i2 < m2; i2++)
        {
            int x = 0, y = 0;
            if (dimension == 0)
            {
                x = i1;
                y = i2;
            }
            else if (dimension == 1)
            {
                x = i0;
                y = i2;
            }
            else if (dimension == 2)
            {
                x = i0;
                y = i1;
            }

            result[x, y] = source[i0, i1, i2];
        }

        return result;
    }

它可以推广到任意数量的维度(甚至可以使代码更小更简单)。

答案 1 :(得分:1)

没有调试它,但猜猜它应该可行

 private int[,,] _space = new int[width, height, depth];

    public int[,] GetCrossSection(int position, int dimension)
    {
        if (dimension < 0 || dimension > 2) return null;
        if (position > _space.GetLength(dimension) || position < 0) return null;
        var minMax = new Tuple<int, int>[3];
        var resultXLength = -1;
        var resultYLength = -1;
        for (var i = 0; i < _space.Rank; i++)
        {
            if (i == dimension)
            {
                minMax[i] = new Tuple<int, int>(position, position+1);
            }
            else
            {
                minMax[i] = new Tuple<int, int>(0,_space.GetLength(i));
                if (resultXLength == -1) resultXLength = _space.GetLength(i);
                else resultYLength = _space.GetLength(i);
            }
        }
        var result = new int[resultXLength, resultYLength];
        for (var i = minMax[0].Item1; i < minMax[0].Item2; i++)
            for (var j = minMax[1].Item1; j < minMax[1].Item2; j++)
                for (var k = minMax[2].Item1; k < minMax[2].Item2; k++)
                {
                    switch (dimension)
                    {
                        case 0:
                        {
                            result[j, k] = _space[i, j, k];
                            break;
                        }
                        case 1:
                        {
                            result[i, k] = _space[i, j, k];
                            break;
                        }
                        case 2:
                        {
                            result[i, j] = _space[i, j, k];
                            break;
                        }
                    }
                }
        return result;
    }

答案 2 :(得分:1)

经过几个星期的其他事情之后,我对Mykola的答案进行了一些回答:

int[,] GetSlice(int[,,] source /*non dynamic 1*/, int dimension, int position)
{
    int dimensions = source.Rank; 
    int[] dims = new int[dimensions-1];

    for(int j = 0; j < dims.Length; j++){
        dims[j] = source.GetLength(j + (j >= dimension ? 1 :0));
    }

    var result = new int[dims[0], dims[1]]; // non dynamic 2

    int[] start = new int[dimensions];
    int[] end = new int[dimensions];
    for(int i = 0; i < dimensions; i++){
        start[i] = dimension == i ? position : 0;
        end[i] = dimension == i ? position + 1 : source.GetLength(i);
    }

    int[] counters = new int[dimensions];
    for (counters[0] = start[0]; counters[0] < end[0]; counters[0]++)
    for (counters[1] = start[1]; counters[1] < end[1]; counters[1]++)
    for (counters[2] = start[2]; counters[2] < end[2]; counters[2]++) // non dynamic 3
    {
        int[] sliceCoord = new int[dimensions-1];

        for(int i = 0; i < t.Length; i++){
            sliceCoord[i] = counters[i + (i >= dimension ? 1 :0)];
        }

        result[sliceCoord[0], sliceCoord[1]] = source[counters[0], counters[1], counters[2]]; // non dynamic 4
    }

    return result;
}

结论:如果您不想采用这种动态行为,则数组不是执行此操作的数据结构。

上面的代码有点像我在写这个问题时想象的那样。如果你想增加维度数量,你还需要改变4个地方。目前没有办法用数组干净利落地做到这一点。

更新:您似乎可以进一步概括代码,因为您可以创建动态排名数组。 Programatically Declare Array of Arbitrary Rank然而,这似乎是性能损失,这很可能是不可接受的

类似问题供参考:How to get a dimension (slice) from a multidimensional array