2017-04-07 142 views
3

的横截面假设你有在C#如何获得3维数组c#

int space[width, height, depth]; 

3维数组,你想实现的方法

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

在哪里“位置”是指定您想要提取切片的“维度”点。 而不是使用我们只处理3维的事实很重要,在下面的示例中,您可以通过添加if语句来修复它们,并假定矩阵不会超出3维。

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

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

我的第二次尝试,同样是无用的:

public int[,] GetCrossSection(int position, int dimension) 
{ 
    int[,] dimensionIterationInterval = new int[,] { { 0, width }, { 0, height }, { 0, depth } }; 
    dimensionIterationInterval[dimension, 0] = position; 
    dimensionIterationInterval[dimension, 1] = position + 1; 

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

这两项attemps碰上死角。你会如何解决它?没有固定迭代循环的空间维数[,,]。如果维度的数量增加,这是有点可管理的。聪明/有限,如果陈述可以工作,但不是每个维度过多ifs。

+0

巧语具体的东西赞赏,但我也是一个“伪的codeY感兴趣的问题如果有一些结构可以用来解决我在两次尝试中遇到的问题, – Adam

回答

1

做其他事情的几个星期后,并与尼古拉的回答乱搞了一下我到达后:

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

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

没有调试它,但你猜它应该工作

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