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

时间:2014-05-26 12:02:41

标签: arrays multidimensional-array go dynamic-arrays

我正在尝试在Go中创建一个二维数组:

board := make([][]string, m)
for i := range board {
    board[i] = make([]string, n)
}

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


背景:

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

3 个答案:

答案 0 :(得分:12)

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

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

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

答案 1 :(得分:3)

您描述的方式会创建一片切片,看起来类似于您想要的二维数组。我建议你将类型更改为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]
}

这将最终只有2个分配,切片将保持数据局部性。请注意,您仍然可以使用2d格式M访问M[2][6]

一个好的video,它解释了如何更快地完成这项工作。

答案 2 :(得分:1)

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

  1. 您知道编译时数组的大小
  2. 您只能在运行时了解数组维,即可以从用户那里了解 输入左右

对于用例1

matr := [5][5]int{}

对于用例2

var m, n int
fmt.Scan(&m, &n)
var mat = make([][]int, m)
for i := range mat {
    mat[i] = make([]int, m)
    fmt.Println(i)
}

简而言之,我们必须依靠make来创建动态数组