簡體   English   中英

按位置獲取數組元素的最優雅方法?

[英]Most elegant way to get the array element by position?

我有一個數組:

private int[,] _blocks = new int[6, 4];

它代表一組水平為6深度,垂直為4深度的塊。 圖形上看起來像這樣:

替代文字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;
}    

但這似乎很浪費,而且味道不好。 有沒有更優雅,更快捷的方法?

在水平方向和垂直方向上,您都可以在數字表中看到一個模式。 您可以通過position / 6確定水平位置,並通過position % 6確定垂直位置-模運算。

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

這在數學上是有意義的。 除法以塊為單位增加,而模(除法余數)一一增加。 數學很簡單。

我不確定我是否遵循,但是為什么您不能僅根據位置計算他的索引? 像這樣:

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

我想你可以這樣:

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

數組中的數字是ACTUALLY 1,2,3,...,還是僅以它們為例?

如果陣列中的數據沒有任何可利用的模式,那么看起來簡單化選項可能是最好的選擇。

或者,您始終可以一次性傳遞整個結構,並構建一個哈希表以供后續調用使用...

根據您對優雅的定義,以下可能是解決問題的更實用的方法:

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

如果需要,我會提供一個更靈活的功能,可以在其他地方使用

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];
}

考慮到極端情況的綜合解決方案:

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];
    }
}
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];
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM