最近又开始扒算法了,很多地方涉及到多维可变切片、数组,用go声明这些声明的我头疼,所以一直在找一个可以简明扼要声明可变切片的方法,但是好像并没有:[,此篇仅摘录一些解释
因为大部分题目,需要写个函数处理不同长度的字符串/数组等,所以切片的长度无法固定,以下是我查到的声明可变切片的方法
// 方法0
row, column := 3, 4 // row and column are`t constant
var answer [][]int
for i := 0; i < row; i++ {
inline := make([]int, column)
answer = append(answer, inline)
}
fmt.Println(answer)
// 方法1
answer1 := make([][]int, row)
for i := range answer1 {
answer1[i] = make([]int, column)
}
fmt.Println(answer1)
// 方法2
answer2 := make([][]bool, row)
for i := 0; i < row; i++ {
lenths[i] = make([]bool, column)
}
明显声明一个二维切片要写至少三四行,我是很不喜欢这种风格,特别是如果不止二维的情况下岂不是要不停嵌套?所以就去查了下,果然*也有个同病相怜的孩纸
Q:
I think that iterating through each slice to initialize it is too verbose. And if the slice had more dimensions, the code would become unwieldy. Is there a concise way to initialize 2D (or n-dimensional) slices in Go?
A:
There isn't a more concise way, what you did is the "right" way; because slices are always one-dimensional but may be composed to construct higher-dimensional objects. See this question for more details: Go: How is two dimensional array's memory representation.
One thing you can simplify on it is to use the for range construct:
a := make([][]uint8, dy)
for i := range a {
a[i] = make([]uint8, dx)
}
Also note that if you initialize your slice with a composite literal, you get this for "free", for example:
a := [][]uint8{
{0, 1, 2, 3},
{4, 5, 6, 7},
}
fmt.Println(a) // Output is [[0 1 2 3] [4 5 6 7]]
Yes, this has its limits as seemingly you have to enumerate all the elements; but there are some tricks, namely you don't have to enumerate all values, only the ones that are not the zero values of the element type of the slice. For more details about this, see Keyed items in golang array initialization.
For example if you want a slice where the first 10 elements are zeros, and then follows 1 and 2, it can be created like this:
b := []uint{10: 1, 2}
fmt.Println(b) // Prints [0 0 0 0 0 0 0 0 0 0 1 2]
Also note that if you'd use arrays instead of slices, it can be created very easily:
c := [5][5]uint8{}
fmt.Println(c)
Output is:
[[0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]
In case of arrays you don't have to iterate over the "outer" array and initialize "inner" arrays, as arrays are not descriptors but values. See blog post Arrays, slices (and strings): The mechanics of 'append' for more details.
Try the examples on the Go Playground.