【问题标题】:How to create a three-dimensional array in Golang如何在 Golang 中创建一个三维数组
【发布时间】:2016-02-28 20:10:16
【问题描述】:

我正在尝试创建一个包含块的三维数组(如魔方)。

我尝试了很多东西,但我无法让它发挥作用。

func generateTiles(x int, y int, z int) [][][]*tile{
  var tiles [][][]*tile

  // Something here
  // resulting in a x by y by z array
  // filled with *tile

  return tiles
}

有什么建议吗?

【问题讨论】:

  • 我想我已经解决了,见下文。
  • 这是一个切片而不是一个数组。

标签: arrays go


【解决方案1】:

你必须自己初始化每一层。示例(on play):

tiles = make([][][]*tile, x)

for i := range tiles {
    tiles[i] = make([][]*tile, y)
    for j := range tiles[i] {
        tiles[i][j] = make([]*tile, z)
    }
}

【讨论】:

  • 谢谢,这更有意义。
【解决方案2】:

出于性能原因,我个人会使用一维切片,我将其添加为替代方案:

type Tile struct {
    x, y, z int
}

type Tiles struct {
    t       []*Tile
    w, h, d int
}

func New(w, h, d int) *Tiles {
    return &Tiles{
        t: make([]*Tile, w*h*d),
        w: w,
        h: h,
        d: d,
    }
}

// indexing based on http://stackoverflow.com/a/20266350/145587
func (t *Tiles) At(x, y, z int) *Tile {
    idx := t.h*t.w*z + t.w*y
    return t.t[idx+x]
}

func (t *Tiles) Set(x, y, z int, val *Tile) {
    idx := t.h*t.w*z + t.w*y
    t.t[idx+x] = val
}

func fillTiles(w int, h int, d int) *Tiles {
    tiles := New(w, h, d)

    for x := 0; x < w; x++ {
        for y := 0; y < h; y++ {
            for z := 0; z < d; z++ {
                tiles.Set(x, y, z, &Tile{x, y, z})
            }
        }
    }

    return tiles
}

playground

【讨论】:

  • 我以前没有想过这种方法。谢谢!我也试试这个。你能解释一下它将如何节省性能吗?
  • @Patrick 有几个原因,1. 它是一大块连续内存,而不是多个碎片块。 2. 每次访问只有一个边界检查,而不是三个(slice[xyz] vs slice[x][y][z]),如果您正在寻找高性能,可以加起来。
【解决方案3】:

GoByExample 上有一个创建二维数组的示例:https://gobyexample.com/arrays。您应该能够将其扩展为三维案例。

这是我想出的。

代码

package main

import (
    "fmt"
)

type Tile struct {
    value int
}

func create3D( x, y, z int) [][][]*Tile {
    result := make([][][]*Tile,x)
    for i := 0 ; i < x ; i++ {
        result[i] = make([][]*Tile,y);
        for j := 0; j < y; j++ {
            result[i][j] = make([]*Tile,z);
            for k := 0 ; k < z; k++ {
                result[i][j][k] = new(Tile)
                result[i][j][k].value = i + j + k;
            }
        }
    }
    return result
}

func main() {
    X := 3
    Y := 4
    Z := 5

    mat := create3D( X , Y , Z);
    for i := 0; i < X; i++ {
        for j := 0 ; j < Y; j++ {
            for k := 0 ; k < Z; k++ {
                fmt.Printf("%d ",mat[i][j][k].value)
            }
            fmt.Println();
        }
        fmt.Println();
    }

}

【讨论】:

    【解决方案4】:

    它是这样工作的,但对我来说这感觉非常低效。多次使用附加操作。而且感觉很臃肿,这应该可以用更简单的方式实现。

    func generateTiles(x int, y int, z int) [][][]*tile {
        var tiles [][][]*tile
    
        for i := 0; i < z; i++ {
            var layer [][]*tile
            for j := 0; j < y; j++ {
                var row []*tile
                for k := 0; k < x; k++ {
                    var t *tile
                    t = &tile{}
                    row = append(row, t)
                    count++
                }
                layer = append(layer, row)
            }
            tiles = append(tiles, layer)
        }
    
        return tiles
    }
    

    【讨论】:

    • 3d 数组很难看,它们具有三个维度。 @nemo 上面有一个更简洁的算法。
    • 如果您使用数组(您的代码使用不是数组的切片)会更容易。
    猜你喜欢
    • 1970-01-01
    • 2020-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-13
    • 1970-01-01
    • 2018-05-14
    • 2019-01-21
    相关资源
    最近更新 更多