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

根据Go之旅,在 Go 切片中s,表达式s[lo:hi]计算为从lo到的元素的切片hi-1,包括:


package main


import "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?感觉不直观,但一定有某种原因让我失踪,我很好奇那可能是什么。


湖上湖
浏览 195回答 2
2回答

潇潇雨雨

这完全是一个约定问题,当然还有其他方法可以做到(例如,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 {&nbsp; &nbsp; ret := make([][]int, 0)&nbsp; &nbsp; i, j := 0, 1&nbsp; &nbsp; for j < len(ints) {&nbsp; &nbsp; &nbsp; &nbsp; if ints[j] != ints[j-1] + 1 {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ret = append(ret, ints[i:j])&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; i = j&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; ret = append(ret, ints[i:j])}(这段代码显然不能很好地处理一些边缘情况,但你明白了)如果我们尝试使用 inclusive-inclusive 切片来编写等效的函数,它会复杂得多。如果有人能想到更多,请随时编辑此答案并添加它们。

眼眸繁星

Go 编程语言规范切片类型切片表达式对于字符串、数组、指向数组的指针或切片 a,主要表达式a[low&nbsp;:&nbsp;high]构造一个子串或切片。索引 low 和 high 选择操作数 a 的哪些元素出现在结果中。结果的索引从 开始,0长度等于high - low。为方便起见,可以省略任何索引。缺失的低指数默认为零;缺少的高索引默认为切片操作数的长度对于数组或字符串,如果 0 <= low <= high <= len(a),则索引在范围内,否则它们超出范围。对于切片,索引上限是切片容量 cap(a) 而不是长度。常量索引必须是非负的并且可以用 int 类型的值表示;对于数组或常量字符串,常量索引也必须在范围内。如果两个指数都是常数,则它们必须满足 low <= high。如果索引在运行时超出范围,则会发生运行时恐慌。对于q := p[m:n],q是p从 index 开始m的一段n-m元素长度的切片。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go