2009-12-03 267 views
0

我有一个数组:最优雅的方式来获取数组元素的位置?

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

这实际上是http://stackoverflow.com/questions/1817631/的副本。 – jason 2009-12-03 02:10:36

+0

你的数组是否真的总是填满所显示的数字,并按照这个确切的顺序?或者仅仅是为了演示的目的,实际上这些数字可以随意改动? – 2009-12-03 02:14:35

回答

6

我不确定我是否遵循,但为什么你不能仅仅根据职位计算他的指数?像这样:

return _blocks[((position - 1) % 6),((position + 5)/6) - 1]; 
10

无论是在水平方向和垂直方向,你可以看到你的数字表中的模式。您可以使用position/6来确定水平位置,使用position % 6来确定水平位置 - 模数运算。

private int GetBlockByPosition(int position) 
{ 
    return _blocks[((position + 6)/6) - 1, position % 6]; 
} 

这使数学意义。分区增加,模数(分区余数)逐个增加。数学很简单。

+0

对于'position = 5',正确答案应该是'[0,4]',对于'position = 6',答案是'[0,5]'。你的代码似乎没有输出它们,所以我想一些调整是必要的。 – 2009-12-03 02:16:31

+0

指数超出界限= 4 – AngryHacker 2009-12-04 02:06:53

2

我认为你可以这样做:

private int GetBlockByPosition(int position) 
{ 
    return _blocks[(position - 1) % 6 , (position - 1)/6]; 
} 
1

实际上是1,2,3,...或者你只是使用它们作为一个例子你的数组中的数字?

如果数组中的数据没有任何模式可以利用,那么它看起来像简单的选项可能是您最好的选择。

或者你总是可以让整个结构的一次性合格,并建立一个哈希表在后续调用中使用...

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(); 
    } 
} 
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]; 
} 
1

综合s内使用更灵活的功能olution考虑极端案例:

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]; 
    } 
} 
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]; 
} 
相关问题