在 Java 中检查二维数组中的邻居的更有效方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4120609/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 11:49:39  来源:igfitidea点击:

More efficient way to check neighbours in a two-dimensional array in Java

javaexceptionperformancemultidimensional-array

提问by Sean Kelleher

Hey all, for a few of my college assignments I've found the need to check neighbouring cells in 2-dimensional arrays (grids). The solution I've used is a bit of a hack using exceptions, and I'm looking for a way to clean it up without having loads of ifstatements like some of my classmates. My current solution is

大家好,对于我的一些大学作业,我发现需要检查二维数组(网格)中的相邻单元格。我使用的解决方案有点使用异常,我正在寻找一种方法来清理它,而不会if像我的一些同学那样有大量的语句。我目前的解决方案是

for ( int row = 0; row < grid.length; row++ ) {
    for ( int col = 0; col < grid.length; col++ ) {
        // this section will usually be in a function
        // checks neighbours of the current "cell"
        try {
            for ( int rowMod = -1; rowMod <= 1; rowMod++ ) {
                for ( int colMod = -1; colMod <= 1; colMod++ ) {
                    if ( someVar == grid[row+rowMod][col+colMod] ) {
                        // do something
                    }
                }
            }
        } catch ( ArrayIndexOutOfBoundsException e ) {
            // do nothing, continue
        }
        // end checking neighbours
    }
}

I shudder to think of the inefficiency using exceptions to get my code to work causes, so I'm looking for suggestions as to how I could remove the reliance on exceptions from my code without sacrificing readability if it's possible, and just how I could make this code segment generally more efficient. Thanks in advance.

我不寒而栗地想到使用异常来让我的代码工作的低效率原因,所以我正在寻找关于如何在不牺牲可读性的情况下从我的代码中消除对异常的依赖的建议,以及我如何做到这个代码段一般效率更高。提前致谢。

回答by DennyRolling

why can't you check row+rowMod and col+colMod for validity before array access?

为什么不能在访问数组之前检查 row+rowMod 和 col+colMod 的有效性?

something like:

就像是:

 r=row+rowMod;
 c=col+colMod;
 if (r < 0 || c < 0 || r >= grid.length || c >= grid.length) continue;

alternatively (no continue):

或者(不继续):

 if (r >= 0 && c >= 0 && r < grid.length && c < grid.length && 
     someVar == grid[r][c]) { /* do something */ }

回答by Mark Elliot

The basic principle is not to access things that are out of bounds -- so either protect the bounds or don't go out of bounds in the first place. That is, start at a place where you won't immediately go out of bounds and stop before you get out of bounds.

基本原则是不要访问越界的东西——所以要么保护界限,要么首先不要越界。也就是说,从一个你不会立即出界的地方开始,在你出界之前停下来。

for ( int row = 1; row < grid.length - 1; row++ ) {
    for ( int col = 1; col < grid.length - 1; col++ ) {
        // this section will usually be in a function
        // checks neighbours of the current "cell"
        for ( int rowMod = -1; rowMod <= 1; rowMod++ ) {
            for ( int colMod = -1; colMod <= 1; colMod++ ) {
                if ( someVar == grid[row+rowMod][col+colMod] ) {
                    // do something
                }
            }
        }
        // end checking neighbours
    }
}

Like your current code, this doesn't necessarily deal appropriately with edge conditions -- that is, it applies a 3x3 grid everywhere that the 3x3 grid fits within the matrix, but does not shrink the grid to a 2x2, 2x3 or 3x2 grid when on the edge of the matrix. It will, however, allow a method in the main body checking a 3x3 grid to observe every cell in the matrix.

与您当前的代码一样,这不一定正确处理边缘条件——也就是说,它在 3x3 网格适合矩阵的任何地方应用 3x3 网格,但不会将网格缩小到 2x2、2x3 或 3x2 网格时在矩阵的边缘。但是,它将允许主体中的一种方法检查 3x3 网格来观察矩阵中的每个单元格。

回答by High Performance Mark

If I understand your code correctly, and am correctly guessing your concerns, you're trying to avoid checking a non-existent neighbour when the cell of interest is on one edge of the grid. One approach, which may or may not suit your application, is to put a 1-cell wide border all the way round your grid. You then run your loops across the interior of this expanded grid, and all the cells you check have 4 neighbours (or 8 if you count the diagonally neighbouring cells).

如果我正确理解了您的代码,并且正确地猜测了您的担忧,那么当感兴趣的单元格位于网格的一侧时,您将试图避免检查不存在的邻居。一种可能适合或不适合您的应用程序的方法是在您的网格周围放置一个 1 个单元格宽的边框。然后您在这个扩展网格的内部运行循环,您检查的所有单元格都有 4 个相邻单元格(如果计算对角相邻单元格,则为 8 个)。

回答by Vivek

You can try this. First decide the size of the grid Lets say its 8 X 8 & assign MIN_X = 0, MIN_Y = 0, MAX_X =7, MAX_Y =7

你可以试试这个。首先决定网格的大小让我们说它的 8 X 8 & 分配 MIN_X = 0, MIN_Y = 0, MAX_X =7, MAX_Y =7

Your curren position is represented by thisPosX , thisPosY, then try this:

您当前的位置由 thisPosX 、 thisPosY 表示,然后试试这个:

int startPosX = (thisPosX - 1 < MIN_X) ? thisPosX : thisPosX-1;
int startPosY = (thisPosY - 1 < MIN_Y) ? thisPosY : thisPosY-1;
int endPosX =   (thisPosX + 1 > MAX_X) ? thisPosX : thisPosX+1;
int endPosY =   (thisPosY + 1 > MAX_Y) ? thisPosY : thisPosY+1;


// See how many are alive
for (int rowNum=startPosX; rowNum<=endPosX; rowNum++) {
    for (int colNum=startPosY; colNum<=endPosY; colNum++) {
        // All the neighbors will be grid[rowNum][colNum]
    }
}

you can finish it in 2 loops.

你可以在 2 个循环中完成它。

回答by Sean Kelleher

So rowand colcurrently contain the coordinate of the cell that I want to check the neighbours of. So if I have a class variable called START_OF_GRIDwhich contains 0, my solution would be as follows:

因此rowcol当前包含我要检查其邻居的单元格的坐标。因此,如果我有一个名为START_OF_GRIDcontains的类变量0,我的解决方案如下:

int rowStart  = Math.max( row - 1, START_OF_GRID   );
int rowFinish = Math.min( row + 1, grid.length - 1 );
int colStart  = Math.max( col - 1, START_OF_GRID   );
int colFinish = Math.min( col + 1, grid.length - 1 );

for ( int curRow = rowStart; curRow <= rowFinish; curRow++ ) {
    for ( int curCol = colStart; curCol <= colFinish; curCol++ ) {
        // do something
    }
}

回答by sumit

How about this:

这个怎么样:

private static void printNeighbours(int row, int col, int[][] Data, int rowLen, int colLen)
{
    for(int nextR=row-1; nextR<=row+1; nextR++)
    {
        if(nextR<0 || nextR>=rowLen)
            continue;  //row out of bound
        for(int nextC=col-1; nextC<=col+1; nextC++)
        {
            if(nextC<0 || nextC>=colLen)
                continue;  //col out of bound
            if(nextR==row && nextC==col)
                continue;    //current cell
            System.out.println(Data[nextR][nextC]);
        }
    }
}

回答by Vikas Tiwari

private void fun(char[][] mat, int i, int j){
    int[] ith = { 0, 1, 1, -1, 0, -1 ,-1, 1};
    int[] jth = { 1, 0, 1, 0, -1, -1 ,1,-1};
     // All neighbours of cell
     for (int k = 0; k < 8; k++) {
            if (isValid(i + ith[k], j + jth[k], mat.length)) {
                //do something here 
            }
        }
}

private boolean isValid(int i, int j, int l) {
        if (i < 0 || j < 0 || i >= l || j >= l)
            return false;
        return true;
}