假设你在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不会过多。
答案 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