Fork me on GitHub

Go语言开发-集合类型-修改切片

4.2.3.修改切片

我们可以使用内置的append()函数来为切片追加元素。该函数接受一个被追加的切片和一个或多个要追加的元素作为参数。如果我们需要将一个切片追加到另一个切片,我们就必须要使用…(省略号)操作符来告诉Go语言将要追加的切片作为多个单独的元素。要追加的元素必须要和切片中元素的类型相同。我们可以使用省略号语法将字符串以字节的形式追加到一个字节切片中。

内置的append()函数接受一个切片和一个或多个值作为参数,并返回一个(可能是新的)切片,该切片包含原有切片的元素,并将给定的元素追加到该切片后面。如果原始切片的容量可以容纳新的元素(即,它的长度再加上要追加的元素个数不超过其容量),append()函数将追加的元素置于其空位置或末尾位置,并返回原始切片加上所追加的元素组成的切片,原始切片长度随着添加的元素而增长。如果原始切片没有足够的容量,append()函数会隐式的创建一个新切片并将原始切片中的元素复制进去,再将要追加的元素添加到末尾,最后返回该新切片,因此我们需要将append()的返回值赋值给原始切片变量。

有时我们需要在切片开始处或中间添加元素,而不仅仅是在结尾处。下面的例子使用了一个自定义的 InsertStringSliceCopy()函数,该函数接受一个要添加的切片、一个用于添加的切片和要添加的索引位置作为参数。

自定义的 InsertStringSliceCopy() 函数创建了一个新的切片(这也是为什么切片s在代码片段结尾处未被改变的原因。),并使用内置的copy()函数复制给定的第一个切片并将其添加到第二个切片中。

内置的 copy()函数接受两个具有相同类型的切片(可以是同一个切片的不同部分,可以重叠)作为参数。该函数复制第二个(源)切片中的元素并将它们添加到第一个(目标)切片中并返回复制的元素个数。如果源切片为空,copy()函数就什么也不做。如果目标切片的长度不足以容纳源切片中的元素,那些无法容纳的元素就会被忽略。如果目标切片的容量大于其长度,我们就可以在复制前使用语句slice=slice[:cap(slice)]将其长度增大到其容量大小。

传递到内置的copy()函数中的切片必须是同一类型的,例外情况是当第一个(目标)切片是[]byte时,第二个(源切片)参数可以是[]byte切片或字符串。如果源切片是一个字符串,该字符串会以字节的形式被复制到第一个参数中。

在自定义的InsertStringSliceCopy()函数中,我们首先创建了一个新的切片(这里是result),该切片的容量足以容纳传入的两个切片中所有的元素。接着我们将第一个切片的子切片(slice[:index])复制到result切片中。再接着我们将要添加的切片从我们之前复制子切片时到达的位置(at)开始将其剩余部分复制到result切片中。对于最后一次复制,我们忽略了copy()函数的返回值,因为我们不需要它。最后我们将result切片返回。

如果索引位置为0,则第一个复制语句中slice[:index]将会是slice[:0](即空切片),所以不会执行复制操作。同样,如果索引大于或等于切片的长度,在最后一个复制语句中,slice[index:]将会是slice[len(slice):](同样为空切片),当然复制操作也会被执行。

下面是一个与InsertStringSliceCopy()函数功能类似的函数,但却更简短和简单。不同之处在于,InsertStringSlice()函数会修改原始切片(也可能是用于添加的切片),而InsertStringSliceCopy()函数则不会。

InsertStringSlice()函数将原始切片从给定的索引位置开始到结尾的元素添加到用于添加的切片中,然后将产生的切片追加到原始切片从给定的索引位置到结尾的位置,返回的切片是原始切片加上用于添加的切片。( append()函数接受一个切片和一个或多个值作为参数,所以我们必须使用省略号语法将切片转化为单个的元素,在这个例子中,我们不得不这样做了两次。)

我们可以使用Go语言的标准切片语法将元素从切片的开始和结尾处删除,但是从中间将其删除就需要小心一点。接下来我们将演示如何从切片的开始、结尾和中间删除元素,然后是演示如何删除切片副本中的元素,而原始切片保持不变。

通过再次切片可以很容易的从切片的开始处删除元素。

下面是通过再次切片从切片的结尾处删除元素,与从切片的开始处删除元素一样。

从切片的中间检索元素是很容易的,例如,要得到切片s中间的三个元素,我们可以使用表达式s[2:5]。但是要从切片中间删除元素稍微有点困难。这里我们使用append()函数完成了删除操作,就是我们将要删除的元素后面的切片s的子切片追加到要删除的元素前面的切片s的子切片中,并将结果赋值回s。

很明显,使用append()函数并将结果赋值回原始切片来删除元素将导致原始切片被修改。下面的例子使用了一个自定义的RemoveStringSliceCopy()函数,该函数返回的是给定切片的副本,但删除了从给定的开始和和结束索引位置之间的元素。

因为RemoveStringSliceCopy()函数复制了原始切片的元素,所以原始切片保持不变。

在自定义的RemoveStringSliceCopy()函数中,我们首先创建了一个新的切片(这里是result),该切片有足够大的容量来容纳将要添加的元素;然后我们将源切片中从开始到start索引位置之间(slice[:start])的元素复制到result切片中;接下来我们将源切片从end索引位置到结尾之间(slice[end:])的元素复制到result切片中;最后返回result切片。

我们也可以创建一个更简单的RemoveStringSlice()函数,该函数作用于给定的切片而不是切片的副本。

这是对之前使用append()函数删除切片中间位置元素的概括。其返回的是将原始切片从start索引位置(但不包括)到end索引位置之间的元素删除后的切片。


目录


作者:Johnson
原创文章,版权所有,转载请保留原文链接。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注