出乎意料的是我的代码基于`map [int] [] [] int`的结果

时间:2017-04-15 12:15:15

标签: go

我在Linux(Ubuntu 1604)/ amd64上的Go版本1.7.4,1.8,1.8.1中运行了我的代码

我正在尝试使用结构m := map[int][][]int编写代码来执行以下操作。

对于数组numbers := []int{0,1,2,3,4},请m[0] = [][]int{[]int{0}, []int{1}, []int{2}, []int{3}, []int{4}}, 并在n中将numbers附加到m[i]的所有列表,然后m[1],如下所示。

m[1] -> [[0,1], [0,2],..,[0,4],[1,2],[1,3],..,[1,4],...,,[2,3],[2,4],[3,4]]

m[2] -> [[0,1,2],[0,1,3],.....]m[3]m[4]

这是我的代码。

package main

import (
    "fmt"
)

func main() {
    n := 5
    m := make(map[int][][]int)
    list := make([][]int, 0)
    for i := 0; i < n; i++ {
        list = append(list, []int{i})
    }
    m[0] = list
    fmt.Println(m)
    for level := 1; level < n; level++ {
        newlist := make([][]int, 0)
        for _, lst := range m[level-1] {
            for i := 0; i < n; i++ {
                if i > lst[len(lst)-1] {
                    newlst := append(lst, i)
                    newlist = append(newlist, newlst)
                    fmt.Println(level, ":", lst, i, "->", newlst, "=>", newlist)
                }
            }
        }
        m[level] = newlist
    }
    fmt.Println(m)
}

输出如下。

map[0:[[0] [1] [2] [3] [4]]]
1 : [0] 1 -> [0 1] => [[0 1]]
1 : [0] 2 -> [0 2] => [[0 1] [0 2]]
1 : [0] 3 -> [0 3] => [[0 1] [0 2] [0 3]]
1 : [0] 4 -> [0 4] => [[0 1] [0 2] [0 3] [0 4]]
1 : [1] 2 -> [1 2] => [[0 1] [0 2] [0 3] [0 4] [1 2]]
1 : [1] 3 -> [1 3] => [[0 1] [0 2] [0 3] [0 4] [1 2] [1 3]]
1 : [1] 4 -> [1 4] => [[0 1] [0 2] [0 3] [0 4] [1 2] [1 3] [1 4]]
1 : [2] 3 -> [2 3] => [[0 1] [0 2] [0 3] [0 4] [1 2] [1 3] [1 4] [2 3]]
1 : [2] 4 -> [2 4] => [[0 1] [0 2] [0 3] [0 4] [1 2] [1 3] [1 4] [2 3] [2 4]]
1 : [3] 4 -> [3 4] => [[0 1] [0 2] [0 3] [0 4] [1 2] [1 3] [1 4] [2 3] [2 4] [3 4]]
2 : [0 1] 2 -> [0 1 2] => [[0 1 2]]
2 : [0 1] 3 -> [0 1 3] => [[0 1 2] [0 1 3]]
2 : [0 1] 4 -> [0 1 4] => [[0 1 2] [0 1 3] [0 1 4]]
2 : [0 2] 3 -> [0 2 3] => [[0 1 2] [0 1 3] [0 1 4] [0 2 3]]
2 : [0 2] 4 -> [0 2 4] => [[0 1 2] [0 1 3] [0 1 4] [0 2 3] [0 2 4]]
2 : [0 3] 4 -> [0 3 4] => [[0 1 2] [0 1 3] [0 1 4] [0 2 3] [0 2 4] [0 3 4]]
2 : [1 2] 3 -> [1 2 3] => [[0 1 2] [0 1 3] [0 1 4] [0 2 3] [0 2 4] [0 3 4] [1 2 3]]
2 : [1 2] 4 -> [1 2 4] => [[0 1 2] [0 1 3] [0 1 4] [0 2 3] [0 2 4] [0 3 4] [1 2 3] [1 2 4]]
2 : [1 3] 4 -> [1 3 4] => [[0 1 2] [0 1 3] [0 1 4] [0 2 3] [0 2 4] [0 3 4] [1 2 3] [1 2 4] [1 3 4]]
2 : [2 3] 4 -> [2 3 4] => [[0 1 2] [0 1 3] [0 1 4] [0 2 3] [0 2 4] [0 3 4] [1 2 3] [1 2 4] [1 3 4] [2 3 4]]
3 : [0 1 2] 3 -> [0 1 2 3] => [[0 1 2 3]]
3 : [0 1 2] 4 -> [0 1 2 4] => [[0 1 2 4] [0 1 2 4]]
3 : [0 1 3] 4 -> [0 1 3 4] => [[0 1 2 4] [0 1 2 4] [0 1 3 4]]
3 : [0 2 3] 4 -> [0 2 3 4] => [[0 1 2 4] [0 1 2 4] [0 1 3 4] [0 2 3 4]]
3 : [1 2 3] 4 -> [1 2 3 4] => [[0 1 2 4] [0 1 2 4] [0 1 3 4] [0 2 3 4] [1 2 3 4]]
map[4:[] 0:[[0] [1] [2] [3] [4]] 1:[[0 1] [0 2] [0 3] [0 4] [1 2] [1 3] [1 4] [2 3] [2 4] [3 4]] 2:[[0 1 2] [0 1 3] [0 1 4] [0 2 3] [0 2 4] [0 3 4] [1 2 3] [1 2 4] [1 3 4] [2 3 4]] 3:[[0 1 2 4] [0 1 2 4] [0 1 3 4] [0 2 3 4] [1 2 3 4]]]

这里的问题。

3 : [0 1 2] 3 -> [0 1 2 3] => [[0 1 2 3]]
3 : [0 1 2] 4 -> [0 1 2 4] => [[0 1 2 4] [0 1 2 4]]           
3 : [0 1 3] 4 -> [0 1 3 4] => [[0 1 2 4] [0 1 2 4] [0 1 3 4]]
3 : [0 2 3] 4 -> [0 2 3 4] => [[0 1 2 4] [0 1 2 4] [0 1 3 4] [0 2 3 4]]
3 : [1 2 3] 4 -> [1 2 3 4] => [[0 1 2 4] [0 1 2 4] [0 1 3 4] [0 2 3 4] [1 2 3 4]]

正确的输出应该是:

3 : [0 1 2] 3 -> [0 1 2 3] => [[0 1 2 3]]
3 : [0 1 2] 4 -> [0 1 2 4] => [[0 1 2 **3**] [0 1 2 4]]           
3 : [0 1 3] 4 -> [0 1 3 4] => [[0 1 2 **3**] [0 1 2 4] [0 1 3 4]]
3 : [0 2 3] 4 -> [0 2 3 4] => [[0 1 2 **3**] [0 1 2 4] [0 1 3 4] [0 2 3 4]]
3 : [1 2 3] 4 -> [1 2 3 4] => [[0 1 2 **3**] [0 1 2 4] [0 1 3 4] [0 2 3 4] [1 2 3 4]]

我不知道为什么,但我认为这可能是Go编译器或运行时的错误。

问题的原因是什么?也许是Go bug或者只是我的代码错误。如果Go或我的代码有bug,如何解决?干杯!

1 个答案:

答案 0 :(得分:2)

在此代码中,您的切片可能会互为别名:

newlist := make([][]int, 0)
for _, lst := range m[level-1] {
    for i := 0; i < n; i++ {
        if i > lst[len(lst)-1] {
            newlst := append(lst, i)
            newlist = append(newlist, newlst)

您将i附加到先前计算的切片,该切片可能会也可能不会重新分配基础数组。如果没有,则每个newlst会重复使用相同的基础数组,因此在早期版本的newlst中,newlst的更高版本会覆盖值。

您需要通过复制数据强制新切片使用新的基础数组:

newlst := append([]int{}, lst...)
newlst = append(newlst, i)

Here's a playground version of the fixed code.