我正在修改矩阵的周长值,然后尝试递归到内部值。我希望可以使用matrix[1:3][1:3]
之类的东西来访问内部值。事实并非如此,我对于Go如何处理顺序括号的基本逻辑有些困惑。
package main
import (
"fmt"
)
var m = [][]int{
[]int{0, 1, 2, 3},
[]int{4, 5, 6, 7},
[]int{8, 9, 10, 11},
[]int{12, 13, 14, 15},
}
我正在尝试访问上述矩阵(“内部”矩阵)中的值5、6、9、10。
func main() {
inner := m[1:3][1:3]
fmt.Printf("%#v\n", inner)
// Expected Output: [][]int{
// []int{5, 6},
// []int{9, 10}
// }
// Actual Ouput: [][]int{
// []int{8, 9, 10, 11},
// []int{12, 13, 14, 15}
// }
inner = m[1:3]
fmt.Printf("%#v\n", inner)
// Output:
// [][]int{
// []int{4, 5, 6, 7},
// []int{8, 9, 10, 11}
// }
inner = innerMatrix(m)
fmt.Printf("%#v\n", inner)
// [][]int{
// []int{5, 6},
// []int{9, 10}
}
func innerMatrix(m [][]int) (inner [][]int) {
innerRows := m[1:3]
for _, row := range innerRows {
inner = append(inner, row[1:3])
}
return
}
函数innerMatrix能够产生我期望的输出。我不知道为什么(1)m[1:3][1:3]
效果不一样,(2)它似乎转换为m[2:4]
。发生了什么事?
答案 0 :(得分:1)
在Go中创建子切片时,您可以将该子切片再次增大回原始切片的容量,例如:
package main
import "fmt"
func main() {
a := []int{1, 2, 3, 4, 5}
b := a[1:3]
fmt.Printf("a[1:3]: %v\n", b)
c := b[1:3]
fmt.Printf("b[1:3]: %v\n", c)
}
输出:
a[1:3]: [2 3]
b[1:3]: [3 4]
请注意,b
仅包含两个元素,但是我们允许创建第二个元素和第三个元素的切片,因为该切片作为子切片的容量足够大,并且所有切片共享相同的基础数组。请参见this page
所以您的情况是m[1:3]
等效于:
var m1 = [][]int{
[]int{4, 5, 6, 7}, // second element of m
[]int{8, 9, 10, 11}, // third element of m
}
和m[1:3][1:3]
等效于m1[1:3]
,等效于:
var m2 = [][]int{
[]int{8, 9, 10, 11}, // second element of m1
[]int{12, 13, 14, 15}, // "third" element of m1
}
出现“第三”元素仅是因为m
的容量足以容纳它,并且实际上包含了它。如果m
仅包含三个元素,则会引起恐慌。
换句话说,m[1:3][1:3]
在这里与m[2:4]
完全等效,因为m[1:3][1:3]
为您提供m[1:3]
的第二个和第三个元素。使用图表可能更容易理解:
m : []int{1, 2, 3, 4}
m[1:3] : []int{ 2, 3 }
m[1:3][1:3] : []int{ 3, 4}
m[2:4] : []int{ 3, 4}
为简化起见,您可以想象方括号将所请求的元素放在其左侧的任何内容中,因此是一个极端的示例:
package main
import "fmt"
func main() {
a := []int{1, 2, 3, 4, 5}
b := a[1:5]
fmt.Printf("b: %v, a[1:5] : %v\n",
b, a[1:5])
c := b[1:4]
fmt.Printf("c: %v , a[1:5][1:4] : %v\n",
c, a[1:5][1:4])
d := c[1:3]
fmt.Printf("d: %v , a[1:5][1:4][1:3] : %v\n",
d, a[1:5][1:4][1:3])
e := d[1:2]
fmt.Printf("e: %v , a[1:5][1:4][1:3][1:2]: %v\n",
e, a[1:5][1:4][1:3][1:2])
}
输出:
b: [2 3 4 5], a[1:5] : [2 3 4 5]
c: [3 4 5] , a[1:5][1:4] : [3 4 5]
d: [4 5] , a[1:5][1:4][1:3] : [4 5]
e: [5] , a[1:5][1:4][1:3][1:2]: [5]
答案 1 :(得分:1)
这是您的数据:
var m = [][]int{
[]int{0, 1, 2, 3},
[]int{4, 5, 6, 7},
[]int{8, 9, 10, 11},
[]int{12, 13, 14, 15},
}
首先,您要问内部是什么:= m [1:3] [1:3]?
好吧,一次取一个,m [1:3]是抓取元素1到3(不包括3)时得到的子切片。因此元素1和2是元素0。[] int {0,1 ,2、3},元素1为[] int {4、5、6、7},元素2为[] int {8、9、10、11},
所以m [1:3]是
[][]int{
[]int{4, 5, 6, 7},
[]int{8, 9, 10, 11},
}
现在,要获得m [1:3] [1:3],我们在此结果上重复同样的事情。 但是,这一次只有两个要素。我们再次需要元素1和2。我们跳过元素0,它是[] int {4,5,6,7}。元素1为[] int {8,9,10,11}。没有元素2。但是,m [1:3]的结果是一个子切片,而基础切片中还有一个附加元素。 因此,通过扩展此子切片,我们可以再次获取该元素,这就是被隐藏的元素2,即[] int {12,13,14,15}。 所以m [1:3] [1:3]是
[][]int{
[]int{8, 9, 10, 11},
[[]int{12, 13, 14, 15},
}
最后,您想知道func innerMatrix为什么会有所不同?首先产生m [1:3],即
[][]int{
[]int{4, 5, 6, 7},
[]int{8, 9, 10, 11},
}
然后,代码不会像m [1:3] [1:3]是两个连续的子切片那样使用另一个子切片。取而代之的是,您获取切片中的每个元素并从每个元素中获取子切片。第一次,您从[] int {4,5,6,7}中获取子切片[1:3]。结果是
[]int{5, 6}
您第二次对第二个元素[] int {8,9,10,11}执行相同的操作
[]int{9, 10}
最后,每次将结果附加到结果切片中,因此将[] int {5,6}附加到[],得到[] [] {int {5,6}},然后您附加[] int {9,10}以提供
[][]{int{5, 6}, []int{9, 10} }