为了账号安全,请及时绑定邮箱和手机立即绑定

在 Go 切片中,为什么 s[lo:hi] 在元素 hi-1 处结束?

在 Go 切片中,为什么 s[lo:hi] 在元素 hi-1 处结束?

Go
湖上湖 2021-08-30 14:40:09
根据Go之旅,在 Go 切片中s,表达式s[lo:hi]计算为从lo到的元素的切片hi-1,包括:package mainimport "fmt"func main() {    p := []int{0,  // slice position 0                10, // slice position 1               20, // slice position 2               30, // slice position 3               40, // slice position 4               50} // slice position 5    fmt.Println(p[0:3]) // => [0 10 20]}    在我上面的代码示例中,“p[0:3]”似乎直观地“读”为:“从位置 0 到位置 3 的切片”,相当于 [0, 10, 20, 30]。但当然,它实际上等同于 [0 10 20]。所以我的问题是:上限值评估为hi-1而不是简单的设计原理是什么hi?感觉不直观,但一定有某种原因让我失踪,我很好奇那可能是什么。
查看完整描述

2 回答

?
潇潇雨雨

TA贡献1833条经验 获得超4个赞

这完全是一个约定问题,当然还有其他方法可以做到(例如,Matlab 使用第一个索引为 1 的数组)。选择实际上取决于您想要什么属性。事实证明,使用 0 索引数组,其中切片是包含不包含的(即,从 a 到 b 的切片包含元素 a 并排除元素 b)具有一些非常好的属性,因此这是一个非常常见的选择。这里有一些优点。


0 索引数组和包含-排除切片的优点


(请注意,我使用的是非 Go 术语,所以我将以 C 或 Java 谈论它们的方式谈论数组。数组就是 Go 所说的切片,而切片是子数组(即“切片从索引 1 到索引 4"))


指针算术有效。如果您使用像 C 这样的语言,数组实际上只是指向数组中第一个元素的指针。因此,如果您使用 0 索引数组,那么您可以说索引i处的元素只是数组指针加i 所指向的元素。例如,如果我们有一个数组[3 2 1],数组的地址为10(假设每个值占用一个字节的内存),那么第一个元素的地址为10 + 0 = 10,则第二个的地址是 10 + 1 = 11,依此类推。简而言之,它使数学变得简单。

切片的长度也是切片的地方。也就是说,对于一个数组arr,arr[0:len(arr)]就是它arr本身。这在实践中非常有用。例如,如果我调用n, _ := r.Read(arr)(其中n是读入的字节数arr),那么我可以只arr[:n]获取与arr实际写入的数据对应的切片arr。

指数不重叠。这意味着如果我有arr[0:i], arr[i:j], arr[j:k], arr[k:len(arr)],这些切片完全覆盖arr自身。您可能不会经常发现自己将数组划分为这样的子切片,但它具有许多相关的优点。例如,考虑以下代码以基于非连续整数拆分数组:


func consecutiveSlices(ints []int) [][]int {

    ret := make([][]int, 0)

    i, j := 0, 1

    for j < len(ints) {

        if ints[j] != ints[j-1] + 1 {

            ret = append(ret, ints[i:j])

            i = j

        }

    }

    ret = append(ret, ints[i:j])

}

(这段代码显然不能很好地处理一些边缘情况,但你明白了)


如果我们尝试使用 inclusive-inclusive 切片来编写等效的函数,它会复杂得多。


如果有人能想到更多,请随时编辑此答案并添加它们。


查看完整回答
反对 回复 2021-08-30
?
眼眸繁星

TA贡献1873条经验 获得超9个赞

Go 编程语言规范

切片类型

切片表达式

对于字符串、数组、指向数组的指针或切片 a,主要表达式

a[low : high]

构造一个子串或切片。索引 low 和 high 选择操作数 a 的哪些元素出现在结果中。结果的索引从 开始,0长度等于high - low

为方便起见,可以省略任何索引。缺失的低指数默认为零;缺少的高索引默认为切片操作数的长度

对于数组或字符串,如果 0 <= low <= high <= len(a),则索引在范围内,否则它们超出范围。对于切片,索引上限是切片容量 cap(a) 而不是长度。常量索引必须是非负的并且可以用 int 类型的值表示;对于数组或常量字符串,常量索引也必须在范围内。如果两个指数都是常数,则它们必须满足 low <= high。如果索引在运行时超出范围,则会发生运行时恐慌。

对于q := p[m:n],qp从 index 开始m的一段n-m元素长度的切片。


查看完整回答
反对 回复 2021-08-30
  • 2 回答
  • 0 关注
  • 194 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信