在Go中初始化一个2d动态数组

arn*_*nab 9 arrays go multidimensional-array dynamic-arrays

我想在Go中创建一个2d数组:

board := make([][]string, m)
for i := range board {
    board[i] = make([]string, n)
}
Run Code Online (Sandbox Code Playgroud)

但是,鉴于其详细程度,我想知道是否有更好或更简洁的方法来处理这个问题(要么生成动态数组,要么使用不同/惯用的数据结构来处理这样的棋盘游戏数据)?


背景:

  • 这是一个棋盘游戏
  • 在用户开始播放之前,不知道电路板的尺寸(例如,MxN).
  • 我想在每个单元格中存储任意字符(或单个字符串).在我的TicTacToe游戏中,它将是'X'或'O'(或用户选择的任何其他角色).

Jam*_*dge 13

您在示例代码中构建的内容不是2D数组,而是切片切片:每个子切片的长度可以与此类型不同,这就是为每个切片分别进行分配的原因.

如果你想用单个分配来表示电路板,一个选项是分配一个片,然后使用简单的算法来确定元素的位置.例如:

board := make([]string, m*n)
board[i*m + j] = "abc" // like board[i][j] = "abc"
Run Code Online (Sandbox Code Playgroud)


Sal*_*ali 8

您描述的方式创建了一个切片切片,它看起来类似于您想要的二维数组。我建议你将类型更改为 uint8,因为你只关心 3 个状态nothing/ first/second玩家。

这会单独分配每一行(至少m + 1 allocs/op在基准测试中您会看到)。这并不是很好,因为不能保证单独的分配会彼此靠近。

为了保持局部性,你可以这样做:

M := make([][]uint8, row)
e := make([]uint8, row * col)
for i := range M {
    a[i] = e[i * col:(i + 1) * col]
}
Run Code Online (Sandbox Code Playgroud)

这最终只会有 2 次分配,并且切片的切片将保持数据局部性。请注意,您仍然可以访问M2d 格式的M[2][6].

一个很好的视频,解释了如何更快地做到这一点。


小智 5

对于多维数组,我们可以有两种用例中的任何一种,

  1. 编译时您知道数组的维度
  2. 您只能在运行时了解数组维度,即可能来自用户输入等

对于用例 1

matr := [5][5]int{}
Run Code Online (Sandbox Code Playgroud)

对于用例 2

var m, n int
fmt.Scan(&m, &n)
var mat = make([][]int, m)
for i := range mat {
    mat[i] = make([]int, n)
    fmt.Printf("Row %d: %v\n", i, mat[i])
}
Run Code Online (Sandbox Code Playgroud)

总之,我们要依赖make创建动态数组