Home > database >  Can't modify a matrix in a function
Can't modify a matrix in a function

Time:12-04

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() <-- returns an array of matrices.

    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
            }
        }
    }
}

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() <-- returns an array of matrices.

    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
            }
        }
    }
}

CodePudding user response:

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 < 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().

CodePudding user response:

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

  •  Tags:  
  • go
  • Related