2009-12-03 270 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]; 
} 
相關問題