在Go语言中,将数组(来自一个映射)添加到切片的切片中。

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

Adding arrays (from a map) to a slice of slices in Go

问题

我有一个带有数组键的地图。
我想将所有的键/数组添加到一个切片的切片中。

然而,我得到了意外的结果。

代码:

package main

import "fmt"

func main() {
	var finalResult [][]int

	set := make(map[[2]int]int)
	a, b, c := [2]int{1, 1}, [2]int{2, 2}, [2]int{3, 3}
	set[a], set[b], set[c] = 1, 1, 1

	fmt.Println("set: ", set)

	for x := range set {

		fmt.Println("\nfinalResult 0: ", finalResult)
		fmt.Println("x: ", x[:])

		finalResult = append(finalResult, x[:])

		fmt.Println("finalResult 1: ", finalResult)

	}
}

输出:

set:  map[[1 1]:1 [2 2]:1 [3 3]:1]

finalResult 0:  []
x:  [1 1]
finalResult 1:  [[1 1]]

finalResult 0:  [[2 2]]
x:  [2 2]
finalResult 1:  [[2 2] [2 2]]

finalResult 0:  [[3 3] [3 3]]
x:  [3 3]
finalResult 1:  [[3 3] [3 3] [3 3]]

在for循环中,finalResult似乎在改变?

有人能解释发生了什么以及如何解决这个问题吗?

英文:

I have a map with arrays for keys.
I want to add all of the keys/arrays to a slice of slices.

However, I am getting unexpected results.

Code:

package main

import "fmt"

func main() {
	var finalResult [][]int

	set := make(map[[2]int]int)
	a, b, c := [2]int{1, 1}, [2]int{2, 2}, [2]int{3, 3}
	set[a], set[b], set[c] = 1, 1, 1

	fmt.Println("set: ", set)

	for x := range set {

		fmt.Println("\nfinalResult 0: ", finalResult)
		fmt.Println("x: ", x[:])

		finalResult = append(finalResult, x[:])

		fmt.Println("finalResult 1: ", finalResult)

	}
}

Output:

set:  map[[1 1]:1 [2 2]:1 [3 3]:1]

finalResult 0:  []
x:  [1 1]
finalResult 1:  [[1 1]]

finalResult 0:  [[2 2]]
x:  [2 2]
finalResult 1:  [[2 2] [2 2]]

finalResult 0:  [[3 3] [3 3]]
x:  [3 3]
finalResult 1:  [[3 3] [3 3] [3 3]]

finalResult appears to be changing during the for loop?

Can someone explain what is happening and how I can work around this issue?

答案1

得分: 2

问题是,你将x局部变量附加到指针finalResult上,所以在每次循环中,x将指向内存中的一个新数组。当你将这个x三次添加到finalResult并打印它时,所有三个x都将指向相同的内存地址。你需要在每次循环中将x指向的内容复制到一个新变量中,并将其添加到finalResult中。

package main

import "fmt"

func main() {
    var finalResult [][]int

    set := make(map[[2]int]int)
    a, b, c := [2]int{1, 1}, [2]int{2, 2}, [2]int{3, 3}
    set[a], set[b], set[c] = 1, 1, 1

    fmt.Println("set: ", set)

    for x := range set {

        fmt.Println("\nfinalResult 0: ", finalResult)
        fmt.Println("x: ", x[:])

        a := make([]int, 2)
        copy(a, x[:])
        finalResult = append(finalResult, a)

        fmt.Println("finalResult 1: ", finalResult)
    }
}

但要注意,遍历映射将始终是随机顺序的,所以你的最终结果可能在每次运行时都会改变。

英文:

The problem is, that you append the x local variable to the finalResult, which is a pointer, so in every for loop, the x will point to a new array in the memory. When you add this x three times to the finalResult and print it, all the three x will be points to the same memory address. You have to copy the content where x points in every loop to a new variable and add this to the finalResult.

package main

import "fmt"

func main() {
	var finalResult [][]int

	set := make(map[[2]int]int)
	a, b, c := [2]int{1, 1}, [2]int{2, 2}, [2]int{3, 3}
	set[a], set[b], set[c] = 1, 1, 1

	fmt.Println("set: ", set)

	for x := range set {

		fmt.Println("\nfinalResult 0: ", finalResult)
		fmt.Println("x: ", x[:])

		a := make([]int, 2)
		copy(a, x[:])
		finalResult = append(finalResult, a)

		fmt.Println("finalResult 1: ", finalResult)
	}
}

But be aware, that ranging over a map will be always in random order, so your final result may change on every run.

huangapple
  • 本文由 发表于 2022年4月30日 01:04:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/72061408.html
匿名

发表评论

匿名网友

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

确定