C# 按位置获取数组元素的最优雅方法?

C# 按位置获取数组元素的最优雅方法?,c#,.net,arrays,C#,.net,Arrays,我有一个数组: private int[,] _blocks = new int[6, 4]; 它表示一组块,水平深度为6,垂直深度为4。从图形上看,它如下所示: return _blocks[((position - 1) % 6),((position + 5) / 6) - 1]; 我需要一个函数,它将接受一个从1到24的数字,并返回匹配的数组元素。所以对于14号,我会回到_块[1,2] 我创建了一个过于简单的函数: private int GetBlockByPosition(int

我有一个数组:

private int[,] _blocks = new int[6, 4];
它表示一组块,水平深度为6,垂直深度为4。从图形上看,它如下所示:

return _blocks[((position - 1) % 6),((position + 5) / 6) - 1];
我需要一个函数,它将接受一个从1到24的数字,并返回匹配的数组元素。所以对于14号,我会回到_块[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;
}    

但这看起来很浪费,而且闻起来很难闻。有没有更优雅、更快捷的方法?

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

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

在水平方向和垂直方向上,都可以在数字表中看到图案。您可以使用位置/6确定水平位置,使用位置%6确定垂直位置-模运算

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

这在数学上是有意义的。除法在块中增加,除法的模余数逐个增加。数学很简单。

我想你可以这样做:

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

数组中的数字实际上是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];
    }
}

这实际上是的副本。您的数组是否总是以精确的顺序填充显示的数字?或者只是为了演示的目的,事实上数字可以被任意洗牌?对于位置=5,正确答案应该是[0,4],对于位置=6,答案是[0,5]。您的代码似乎没有输出它们,所以我想有必要进行一些调整