在一个函数中无法修改矩阵。

huangapple go评论86阅读模式
英文:

Can't modify a matrix in a function

问题

我有一个矩阵数组,并且我尝试在满足某个条件的情况下改变每个矩阵。例如,如果我有以下矩阵:

1 2 3
4 5 6
7 8 9

我想将每个奇数改为0。这是我的代码:

func main() {
    matrices := createMatrix() // 返回一个矩阵数组

    for _, matrix := range matrices {
        removeOdds(matrix)
    }
}

func removeOdds(mat [][]int) {
    for i := 0; i < len(mat); i++ {
        for j := 0; j < len(mat[i]); j++ {
            if mat[i][j] % 2 != 0 {
                mat[i][j] = 0
            }
        }
    }
}

这段代码不起作用,因为矩阵没有被改变。我读到 Go 通过值传递数组而不是引用,所以我尝试使用指针。但是,当我在 removeOdds 改变后打印矩阵时,我得到的仍然是原始的矩阵。

这是我写的代码:

func main() {
    matrices := createMatrix() // 返回一个矩阵数组

    for _, matrix := range matrices {
        removeOdds(&matrix)
    }
}

func removeOdds(mat *[][]int) {
    for i := 0; i < len(*mat); i++ {
        for j := 0; j < len((*mat)[i]); j++ {
            if (*mat)[i][j] % 2 != 0 {
                (*mat)[i][j] = 0
            }
        }
    }
}
英文:

I have an array of matrices and I try to mutate each matrix in case an if statement is true.
for example, if I have this matrix:

1 2 3
4 5 6
7 8 9

I want to change each odd number to 0.
This is what I have:

func main() {

	matrices := createMatrix() &lt;-- returns an array of matrices.

	for _, matrix := range matrices {
		removeOdds(matrix)
	}
}

func removeOdds(mat [][]int) {
	for i := 0; i &lt; len(mat); i++ {
		for j := 0; j &lt; len(mat[i]); j++ {
			if mat[i][j] % 2 != 0 {
				mat[i][j] = 0
			}
		}
	}
}

This is not working because the matrix is not being changed.
I read that Go pass array by value and not reference, so I tried using pointers. But still, when I print the matrix after the changes of removeOdds, I get the original one.

This is what I wrote:

func main() {

	matrices := createMatrix() &lt;-- returns an array of matrices.

	for _, matrix := range matrices {
		removeOdds(&amp;matrix)
	}
}

func removeOdds(mat *[][]int) {
	for i := 0; i &lt; len(*mat); i++ {
		for j := 0; j &lt; len((*mat)[i]); j++ {
			if (*mat)[i][j] % 2 != 0 {
				(*mat)[i][j] = 0
			}
		}
	}
}

答案1

得分: 1

你的第一个方法是正确的,除了对矩阵进行迭代的部分。你应该使用以下代码:

for i := range matrices {
        removeOdds(matrix[i])
}

而不是

for _, matrix := range matrices {
        removeOdds(matrix)
}

链接:https://go.dev/play/p/iE0uCE_6Z2v

英文:

Your first approach is true except iterating over matrices.
You should use

for i := range matrices {
        removeOdds(matrix[i])
}

instead of

for _, matrix := range matrices {
        removeOdds(matrix)
}

https://go.dev/play/p/iE0uCE_6Z2v

答案2

得分: 1

据我所知,代码片段看起来完全没问题。

明确一点,[]int 类型不是数组,而是切片(slice)。数组是一个固定长度的数据块,数组的类型签名应该是 [3]int 这样的形式。切片是一种引用类型,它是对真实数据的可变长度视图,意味着它并不拥有数据,它只记录了在内存中找到数据的位置。

当你将一个切片传递给函数时,该引用值会被复制,即使在函数内部,你仍然引用着相同的数据块,或者可以说是底层的数组,就像在函数范围之外一样。

然而,我自己尝试了你的代码,并写了这个:

type Mat = [][]int

func makeMat() Mat {
	return [][]int{
		{1, 2, 3},
		{4, 5, 6},
		{7, 8, 9},
	}
}

func main() {
	mats := []Mat{}
	for i := 0; i < 10; i++ {
		mats = append(mats, makeMat())
	}
	for _, mat := range mats {
        // 这个函数没有做任何改变
		removeOdds(mat)
	}
	for _, mat := range mats {
		fmt.Println(mat)
	}

}

输出结果:

[[0 2 0] [4 0 6] [0 8 0]]
[[0 2 0] [4 0 6] [0 8 0]]
[[0 2 0] [4 0 6] [0 8 0]]
[[0 2 0] [4 0 6] [0 8 0]]
[[0 2 0] [4 0 6] [0 8 0]]
[[0 2 0] [4 0 6] [0 8 0]]
[[0 2 0] [4 0 6] [0 8 0]]
[[0 2 0] [4 0 6] [0 8 0]]
[[0 2 0] [4 0 6] [0 8 0]]
[[0 2 0] [4 0 6] [0 8 0]]

所以我认为你的观察可能有一些错误。也许提供关于你的 createMatrix() 的更多信息会有所帮助。

英文:

As far as I concerned, the code snippet looks completely ok.

To be clear, type []int is not an array, it's a slice. Array is a fix length block of data, and type signature of array should be like [3]int. Slice is a reference type, a variable length view onto the real data, means it does not own the data, it only record where to find the data in memory in its value.

When you pass a slice into function, that reference value is copied, even inside the function, you are still referencing the same data block, or you can say the underlaying array, as you are when out side function scope.

How ever, I've tried your code my self, and I wrote this:

type Mat = [][]int

func makeMat() Mat {
	return [][]int{
		{1, 2, 3},
		{4, 5, 6},
		{7, 8, 9},
	}
}

func main() {
	mats := []Mat{}
	for i := 0; i &lt; 10; i++ {
		mats = append(mats, makeMat())
	}
	for _, mat := range mats {
        // no change was made to this function
		removeOdds(mat)
	}
	for _, mat := range mats {
		fmt.Println(mat)
	}

}

output:

[[0 2 0] [4 0 6] [0 8 0]]
[[0 2 0] [4 0 6] [0 8 0]]
[[0 2 0] [4 0 6] [0 8 0]]
[[0 2 0] [4 0 6] [0 8 0]]
[[0 2 0] [4 0 6] [0 8 0]]
[[0 2 0] [4 0 6] [0 8 0]]
[[0 2 0] [4 0 6] [0 8 0]]
[[0 2 0] [4 0 6] [0 8 0]]
[[0 2 0] [4 0 6] [0 8 0]]
[[0 2 0] [4 0 6] [0 8 0]]

So I think there may be some mistake in your observation. Maybe provide more information about your createMatrix().

huangapple
  • 本文由 发表于 2021年12月4日 18:59:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/70224977.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定