The task is to write a function that returns all its neighbors for an element. Diagonal elements are not considered neighbors.

In general, the problem is solved, but if the elements fall outside the matrix, the compiler generates runtime error: index out of range [-1] . Now I'm thinking of making a condition that excludes data outside the matrix. Can you tell me how such a condition would look like? I've already tried something like: if element = -1, then remove element from response. But it doesn't work.

package main

import "fmt"

func Input(y, x int) []int {
    matrix := [][]int{
        []int{0, 2, 3},
        []int{2, 3, 1},
        []int{8, 7, 4},
        []int{3, 2, 1},
    }
    k := []int{matrix[y+1][x], matrix[y-1][x], matrix[y][x+1], matrix[y][x-1]}
    for _, z := range k {
        if z == -1 { //error
            return append(k[z:], k[:z-1]...)
        }
    }
    return k
}
func main() {
    fmt.Println(Input(0, 0))
}

推荐答案

Both x and y indices of neighbors may be out of range, and not just when being -1, but also when they are >= length of the slice you index with them.

So basically there are 4 neighbors:

(y-1,x), (y+1, x), (y,x-1), (y,x+1)

You have to check all out of bounds cases. Your panic happens on the k := ... line, not inside the for loop. Also returning early in the loop will not handle all elements, and that for is wrong from its roots.

So basically this is how you could do it:

var result []int

if y > 0 {
    result = append(result, matrix[y-1][x])
}
if y < len(matrix)-1 {
    result = append(result, matrix[y+1][x])
}
if x > 0 {
    result = append(result, matrix[y][x-1])
}
if x < len(matrix[y])-1 {
    result = append(result, matrix[y][x+1])
}

return result

This will output (try it on the Go Playground):

[2 2]

Note that if x or y is already invalid, the above code will still panic. If you want to protect against it, you also have to validate x and y, e.g.:

var result []int
if y < 0 || y >= len(matrix) || x < 0 || x >= len(matrix[y]) {
    return result
}

Another approach is to list the deltaY and deltaX indices of neighbors in another slice:

var neighbors = [][]int{
    {-1, 0},
    {1, 0},
    {0, -1},
    {0, 1},
}

And you may use a loop to iterate over neighbors, and then you can check indices in a single place:

var result []int
for _, neighbor := range neighbors {
    iy, ix := y+neighbor[0], x+neighbor[1]
    if iy < 0 || iy >= len(matrix) || ix < 0 || ix >= len(matrix[iy]) {
        continue
    }
    result = append(result, matrix[iy][ix])
}

return result

Try this one on the Go Playground.

Note that this second solution also returns neighbors if you specify indices outside of the matrix if the neighbor of that element falls inside the matrix. E.g. using y=-1, x=0 as the input, the neighbor (y+1,x) being 0 will be returned.

Go相关问答推荐

Makefile:现有文件上没有这样的文件或目录,不加载环境变量

GORM Find方法中缺少字段

你能把用户界面文件中的GTK4应用程序窗口添加到GTK4应用程序中吗?

无法使用Segentio;S Kafka-Go连接到融合的Kafka

使用Dockertest进行Golang SQL单元测试的基本设置

在VSCode中如何使用特定的文件名提供编译命令

用于提取 <*n 的正则表达式(其中 n 是一个数字)

Go struct 匿名字段是公开的还是私有的?

加载 docker 镜像失败

使用 Golang 在字符串中循环重复数据

未定义 protoc protoc-gen-go 时间戳

vs 代码调试 go 测试不通过标志

golang jwt.MapClaims 获取用户ID

当 git clone 工作时,Go mod tidy 在私有存储库上失败

go 堆栈跟踪:在某些函数调用参数或返回值之后的问题(?)标记是什么意思?

try 执行`go test ./... -v`时,Golang中有没有办法设置标志

如何扩充 ResponseWriter 的 Header() 返回的 map

我应该明确地创建一个与Belongs To或Has Many对称的关系吗?

同一个 Go struct成员上的多个标签

从类型别名转换为原始类型