当前位置: 首页 > 面试题库 >

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

池永长
2023-03-14
问题内容

根据“围棋之旅”,在围棋切片中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?感觉很不直观,但是我一定缺少某些原因,我很好奇这可能是什么。

提前致谢。


问题答案:

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

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

(请注意,我使用的是非Go术语,因此我将以C或Java讨论数组的方式来讨论数组。数组是Go所谓的slice,而slice是子数组(即,“
slice”从索引1到索引4“))

  • 指针算术有效。如果您使用的语言是C,数组实际上只是指向数组中第一个元素的指针。因此,如果使用0索引数组,那么可以说索引 i 处的元素就是数组指针加 i 指向的元素。例如,如果我们有数组[3 2 1],数组的地址为10(并假设每个值占用一个内存字节),则第一个元素的地址为10 + 0 = 10,则第二个地址是10 +1 = 11,依此类推。简而言之,它使数学变得简单。
  • 切片的长度也是切片的地方。也就是说,对于一个数组arrarr[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])
    

    }

(这段代码显然不能很好地处理某些极端情况,但是您知道了)

如果我们尝试使用包含式和包含式切片来编写等效函数,则它将变得更加复杂。

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



 类似资料:
  • 我有一个结构片。 以下是此文件的输出: 如何搜索此数组以获取所在的元素?

  • 主要内容:从开头位置删除,从中间位置删除,从尾部删除Go语言并没有对删除切片元素提供专用的语法或者接口,需要使用切片本身的特性来删除元素,根据要删除元素的位置有三种情况,分别是从开头位置删除、从中间位置删除和从尾部删除,其中删除切片尾部的元素速度最快。 从开头位置删除 删除开头的元素可以直接移动数据指针: 也可以不移动数据指针,但是将后面的数据向开头移动,可以用 append 原地完成(所谓原地完成是指在原有的切片数据对应的内存区间内完成,不会导致

  • 问题内容: 我有一个结构“ Guest”,其中包含聚会客人的元数据(唯一的ID,名称,姓氏以及作为该客人的朋友的客人的唯一ID的列表。 我有以下代码从朋友列表中删除ID: 问题是:我要删除的元素被元素的移位覆盖,但是切片不会变短。而是将切片的最后一个元素相乘。 举一个例子:是。我打电话后,结果却不是理想的。 那么,我在做什么错呢? 问题答案: 任何打算/确实修改接收器的方法都必须使用指针接收器。

  • 问题内容: Swift中的切片是什么,它与数组有何不同? 从文档中,下标(Range)的类型签名为: 为什么不返回另一个而不是一个? 看起来我可以将切片与数组连接起来: 但这会产生错误: 无法找到接受提供的参数的“下标”的重载 什么是切片? 问题答案: 切片指向数组。当数组已经存在并且切片只能描述其所需部分时,再也没有必要制作另一个数组。 加法会导致隐式强制,因此可以正常工作。为了使您的作业正常进

  • 问题内容: 考虑下面的go代码: : 我不明白的是,为什么taste_fruits的容量为3,直觉上我希望为2,因为这是切片的长度? 而且,如果tasty_fruits的容量为3,那么为什么: 造成: 问题答案: 这行: 创建一个 数组 ,而不是一个切片。即使您仅提供了3个元素,它也有4个元素。输出: 切片: 结果是: 长度:明显2.容量? 的 容量 是…的片的长度和超过所述切片中的[基本]阵列的

  • 问题内容: mapArray是float32的2D切片。我对其进行了复制,因此 无需修改mapArray即可进行复制 。但是,事实并非如此。分配一个值进行修改。 这样做将使-1而不是其原始值。 如何制作切片的真实独立副本? 谢谢。 编辑: 问题答案: 2D切片是切片的切片。在您的函数中,您分配一个切片来容纳其他切片,然后为每个切片分配内存来容纳该行数据。要复制它,您需要复制所有这些数据行以及整个切