【问题标题】:How to create slice of nonconsecutive array indices如何创建不连续数组索引的切片
【发布时间】:2020-03-19 18:57:01
【问题描述】:

我正在尝试更好地理解切片。

例如,在 Fortran 中,如果我有一个二维数组,我可以使用 matrix(:, (/2, 5, 9/)) 创建一个切片。此切片仅包含第 2、5 和 9 行。我正在尝试找到一种在 Go 中创建类似切片的方法。

我知道我可以像这样使用 append:

var slice [][N]
slice = append(arr[1],arr[4],arr[8])

并且切片具有正确的值,但append 复制了这些值,因此如果我更新数组,我的切片不会更新。

在 Go 中有合适的方法吗?

【问题讨论】:

    标签: arrays go slice


    【解决方案1】:

    引用Spec: Slice types:

    切片是底层数组的连续段的描述符,并提供对该数组中元素的编号序列的访问。

    切片始终表示底层数组的连续段,不能在开始和结束索引之间跳过元素。

    使用指针切片

    您可以使用指针来模仿这种行为,但是它们将成为具有所有优点和缺点的指针。例如:

    const N = 3
    
    s := make([][N]int, 10)
    s[2] = [3]int{20, 21, 22}
    s[5] = [3]int{50, 51, 52}
    s[9] = [3]int{90, 91, 92}
    
    s2 := []*[N]int{&s[2], &s[5], &s[9]}
    for _, p := range s2 {
        fmt.Print(*p, " ")
    }
    
    s[2][0] = 66
    fmt.Println()
    for _, p := range s2 {
        fmt.Print(*p, " ")
    }
    

    在创建和填充s2(来自s 的元素)之后,我们修改s 的元素,并再次打印s2,我们会看到更改后的更新值。输出(在Go Playground上试试):

    [20 21 22] [50 51 52] [90 91 92] 
    [66 21 22] [50 51 52] [90 91 92]
    

    使用一片切片

    切片(切片标头)类似于指针:它们是类似结构的小型数据结构,其中包含指向切片第一个元素的指针,指向底层数组中的某个位置。详情见Are golang slices passed by value?why slice values can sometimes go stale but never map values?

    因此,如果您使用切片切片而不是数组切片,则它可以在没有指针的情况下工作(切片值已经包含指针)。

    看这个例子:

    s := make([][]int, 10)
    s[2] = []int{20, 21, 22}
    s[5] = []int{50, 51, 52}
    s[9] = []int{90, 91, 92}
    
    s2 := [][]int{s[2], s[5], s[9]}
    fmt.Println(s2)
    
    s[2][0] = 66
    fmt.Println(s2)
    

    这将输出(在Go Playground 上尝试):

    [[20 21 22] [50 51 52] [90 91 92]]
    [[66 21 22] [50 51 52] [90 91 92]]
    

    查看相关问题:How is two dimensional array's memory representation

    【讨论】:

      猜你喜欢
      • 2023-03-22
      • 2020-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-15
      • 2015-01-21
      • 2021-05-30
      • 1970-01-01
      相关资源
      最近更新 更多