2017-04-07 36 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; 
    }