Golang:切片追加在生成二进制序列时无法正常工作

问题描述 投票:1回答:1

我有这段代码生成所有长度为n的二进制序列。所以:

allBitsSeqs(2) gives a 1-by-n int slice  [[1 1][0 0] [1 0] [0 1]]

这里是代码:

func allBitSeqs(n int) [][]int {      
    seq := [][]int{{1}, {0}}
    for floor := 1; floor < n; floor++ {
        remember := [][]int{}
        for i := 0; i < len(seq); i++ {
            one := append(seq[i], 1)
            remember = append(remember, one)
            zero := append(seq[i], 0)
            remember = append(remember, zero)
        }
        seq = remember
    }
    return seq
}

游乐场链接:https://play.golang.org/p/s40RS7qEKfL

问题是,当n = 4或更大时,我得到:

[[1 1 1 0] [1 1 1 0] [1 1 0 0] [1 1 0 0] [1 0 1 0] [1 0 1 0] [1 0 0 0] [1 0 0 0] [0 1 1 0] [0 1 1 0] [0 1 0 0] [0 1 0 0] [0 0 1 0] [0 0 1 0] [0 0 0 0] [0 0 0 0]]

注意它们如何成对重复。我已经尝试了一些调试,并且我认为它与Go需要分配更多空间时如何复制其片段有关。再说一次,我认为它应该一目了然,所以...我不知道这是怎么回事。

go
1个回答
0
投票

切片是基础数组的视图。如果您有多个使用同一基础数组的切片,那么如果您不知道切片的工作方式,则可能会得到意外的结果。

one := append(seq[i], 1)

说,one是指向一个数组的切片,该数组具有容纳添加的元素的能力。类似于以下内容:

[ 1 1 . . .  ]

阵列容量为5,前两个元素设置为1(切片len = 2)。当您添加另一个1时,它将变为:

[ 1 1 1 . .]

然后您执行以下操作:

remember = append(remember, one)

这样,您添加了一个指向上述数组的切片,len = 3,容量= 5。

然后:

zero := append(seq[i], 0)

请记住,seq [i]仍指向同一数组。另外,seq [i]具有len = 2。因此数组变为:

[ 1 1 0 . . ]

即您的zero。但是,当您添加0时,您还更改了切片one。最后,zeroone都指向[1 1 0 . .]

长话短说:将切片分配给变量时,将视图分配给数组。如果您修改基础数组的内容,则视图的内容也会更改。

要解决:创建一个新的切片,复制数据并存储该副本。

© www.soinside.com 2019 - 2024. All rights reserved.