2017-04-15 29 views
0

我跑我的代碼在Go版本1.7.4,1.8,1.8.1在Linux(Ubuntu的1604)/ AMD64不料結果基於我的代碼`圖[INT] [] [] int`

我正在嘗試使用結構m := map[int][][]int編寫代碼來執行下面的操作。

對於數組numbers := []int{0,1,2,3,4},讓m[0] = [][]int{[]int{0}, []int{1}, []int{2}, []int{3}, []int{4}}, 並且如下內numbers附加一個數n到的所有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或我的代碼有bug,該如何解決?乾杯!

+0

以我的經驗,「可能是編譯器或運行時的錯誤」,是路少可能比「可能是我自己的代碼中的錯誤」。確定有時會發生編譯器或運行時被破壞,但這種情況非常罕見。實用的程序員書描述這個想法的座右銘''選擇'沒有壞' –

+0

[一個壞的工作者總是責備他的工具](https://en.oxforddictionaries.com/definition/a_bad_workman_always_blames_his_tools):諺語:一個人做了一件壞事會試圖將責任歸咎於他們的設備,而不是承認自己缺乏技能。 – peterSO

+0

@peterSO明白。謝謝! –

回答

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.

+0

這真的是一個無法理解的陷阱。我看你是對的,但對我的理解並不自然。我認爲'append(lst,i)'應該分配一個大小應該是'len(lst)+ 1'的數組,並將'lst'和'i'的內容複製到新數組中。你能解釋一下這個案例的更多細節嗎?什麼時候會發生? –

+2

僅當附加元素不適合當前數組時才分配新的基礎數組。見:https://blog.golang.org/go-slices-usage-and-internals –

+0

明白了。非常感謝! –