查找3D列表中的所有相邻项目

时间:2013-01-16 00:43:16

标签: c#

我有一个3D列表(3个嵌套列表),对于列表中的每个项目,我需要找到相邻的项目。目前,我正在为每个相邻项创建一个数组,并将其存储在每个项中。这是非常耗费资源的,所以我希望稍微简化一下。

我正在考虑使用这种方法:

for (int i = 0; i < 8; i++)
{
    switch (i)
    {
        case (0):
            mapCell neighbor = myMap.Depth[z].Rows[x].Columns[y - 1];
        case (1):
            mapCell neighbor = myMap.Depth[z].Rows[x].Columns[y + 1];
        case (2):
            mapCell neighbor = myMap.Depth[z].Rows[x - 1].Columns[y];
        case (3):
            mapCell neighbor = myMap.Depth[z].Rows[x + 1].Columns[y];
        case (4):
            mapCell neighbor = myMap.Depth[z].Rows[x + 1].Columns[y + 1];
        case (5):
            mapCell neighbor = myMap.Depth[z].Rows[x + 1].Columns[y - 1];
        case (6):
            mapCell neighbor = myMap.Depth[z].Rows[x - 1].Columns[y + 1];
        case (7):
            mapCell neighbor = myMap.Depth[z].Rows[x - 1].Columns[y - 1];
    }

    // do some stuff with the neighbor here
}

这比我现在的性能好很多,但我想知道是否有更简单的方法来实现这一目标?这看起来有点凌乱,我觉得有一种方法可以在一行中做到这一点,但我只是无法弄清楚数学。

编辑:抱歉,我可能省略了一些重要细节。与“邻居”变量一起使用的代码被遗漏了,因为它很长并且对解决方案没有帮助。我不需要维护一个“邻居”变量列表(这就是我目前正在做的事情,它使用了太多的内存(大约400megs)。我只需要一个快速的方法来查看每个项目,找到每个相邻的8个项目,一次一个地做一些事情,然后移动到下一个节点。上面的代码将通过它们,但它不是最优化的方法来实现它。

1 个答案:

答案 0 :(得分:1)

看起来您实际上是在3D数据结构中给定深度处的2D阵列中找到邻居。即你忽略了相邻深处的邻居。

你的方法可能非常有效。你可以找到一些更低级的打字方式,例如this answer关于SO的类似问题,但我怀疑它会更快。

显然,您还需要在代码中包含一些检查来处理边缘的项目,这些项目不会有8个邻居。

private void DoSomethingWithNeighbours(int x, int y, int z)
{
    foreach (var neighbout in this.GetNeighbours(x, y, z)
    {
        // ...
    }
}

private IEnumerable<Item> GetNeighbours(int x, int y, int z)
{
    if (x > 0)
    {
        if (y > 0)
        {
            yield return myMap.Depth[z].Rows[x - 1].Columns[y - 1];
        }

        yield return myMap.Depth[z].Rows[x - 1].Columns[y];

        if (y < ColumnCount - 1)
        {
            yield return myMap.Depth[z].Rows[x - 1].Columns[y + 1];
        }
    }

    if (y > 0)
    {
        yield return myMap.Depth[z].Rows[x].Columns[y - 1];
    }

    if (y < ColumnCount - 1)
    {
        yield return myMap.Depth[z].Rows[x].Columns[y + 1];
    }

    if (x < RowCount - 1)
    {
        if (y > 0)
        {
            yield return myMap.Depth[z].Rows[x + 1].Columns[y - 1];
        }

        yield return myMap.Depth[z].Rows[x + 1].Columns[y];

        if (y < ColumnCount - 1)
        {
            yield return myMap.Depth[z].Rows[x + 1].Columns[y + 1];
        }
    }
}

或者以下替代方案更简洁,只有很小的性能成本:

private IEnumerable<int> GetNeighbours2(int x, int y, int z)
{
    for (int i = x - 1; i <= x + 1; ++i)
    {
        for (int j = y - 1; j <= y + 1; ++j)
        {
            if (i >= 0 && i < Rows && j >= 0 && j < Cols && !(i == x && j == y))
            {
                yield return myMap.Depth[z].Rows[i].Columns[j];
            }
        }
    }
}