我有一个数组:
private int[,] _blocks = new int[6, 4];
它代表一组水平深6和垂直深4的块。从图形上看,它看起来像这样:
alt text http://www.angryhacker.com/toys/array.png
我需要一个函数,它将接收一个数字,从1到24并返回匹配的数组元素。所以对于14号,我会回到_blocks [1,2];
我创造了一个简单的功能:
private int GetBlockByPosition(int position)
{
int count = 0;
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < 4; j++)
{
if (++count == position)
return _blocks[i, j];
}
}
return -1;
}
但这看起来很浪费,闻起来很糟糕。是否有更优雅,更快捷的方式?
答案 0 :(得分:10)
在水平方向和垂直方向上,您都可以在数字表中看到一个模式。您可以使用position / 6
确定水平位置,使用position % 6
确定垂直位置 - 模运算。
private int GetBlockByPosition(int position)
{
return _blocks[((position + 6) / 6) - 1, position % 6];
}
这具有数学意义。分块增加,模数(除法余数)逐一增加。数学很简单。
答案 1 :(得分:6)
我不确定我会效仿,但为什么你不能根据位置来计算他的指数呢?像这样:
return _blocks[((position - 1) % 6),((position + 5) / 6) - 1];
答案 2 :(得分:2)
我认为你可以这样做:
private int GetBlockByPosition(int position)
{
return _blocks[(position - 1 ) % 6 , (position - 1) / 6];
}
答案 3 :(得分:1)
你的数组中的数字是否真的是1,2,3 ......或者你只是以它们为例?
如果您的阵列中的数据没有任何可以利用的模式,那么看起来简单选项可能是您最好的选择。
或者您总是可以对整个结构进行一次性传递,并构建一个哈希表,以便在后续调用中使用...
答案 4 :(得分:1)
根据您对优雅的定义,以下可能是解决问题的更实用的方法:
class Program
{
static void Main(string[] args)
{
var blocks = new int[,] {{1,2,3,4,5,6},{7,8,9,10,11,12},{13,14,15,16,17,18},{19,20,21,22,23,24}};
var position = blocks.FirstPositionOf(14);
Console.WriteLine(position.X + "," + position.Y + " has the element " + blocks[position.X,position.Y]);
}
}
class PositionTuple
{
public int X {get; set;}
public int Y {get; set;}
}
static class ArrayExtensions
{
public static IEnumerable<int> AsEnumerable(this int[,] someTwoDimensionalArray)
{
foreach (var num in someTwoDimensionalArray)
yield return num;
}
public static PositionTuple FirstPositionOf(this int[,] someTwoDimensionalArray, int someNumber)
{
return someTwoDimensionalArray
.AsEnumerable()
.Select((num, index) => new { Number = num, Tuple = new PositionTuple { X = index / (someTwoDimensionalArray.GetUpperBound(1) + 1), Y = index % (someTwoDimensionalArray.GetUpperBound(1)+1) }})
.Where(pair => pair.Number == someNumber)
.Select(pair => pair.Tuple)
.First();
}
}
答案 5 :(得分:1)
如果需要,我会制作一个更灵活的功能,可以在别处使用
public static T Get2DArrayValueByPosition<T> (T[,] arr, int position)
{
// Gets the size of the array in first dimention
step = arr.GetUpperBound(0) + 1;
return arr[(position / step ), position % step];
}
答案 6 :(得分:1)
考虑角落案例的综合解决方案:
private int GetBlockByPosition(int position)
{
if(position % 6 == 0) { // last cells in each row. 6 gives [0,5]
return _blocks[(position / 6) - 1, (position - 1) % 6];
} else { // 11 gives [1,4]
return _blocks[position / 6 , (position % 6) - 1];
}
}
答案 7 :(得分:1)
int result = GetByPosition(_blocks, 14);
private int GetByPosition(int[,] array, int position)
{
return GetByPositionBaseZero(array, position - 1);
}
private int GetByPositionBaseZero(int[,] array, int position)
{
int width = array.GetLength(0);
return array[position % width, position / width];
}