英文:
Decreasing slice capacity
问题
我的问题是关于切片长度和容量的。我在这里学习Go语言:https://tour.golang.org/moretypes/11。
(我的问题被标记为可能是这个问题的重复;然而,这并不是事实。我的问题特别涉及到切片的前几个元素被截断以及这样做的影响。)
为什么 s = s[2:]
这一行会减少容量,而 s = s[:4]
和 s = s[:0]
不会呢?我唯一看到的区别是在 s = s[2:]
中冒号前面有一个数字,而在其他两行中冒号后面有一个数字。
有没有办法恢复被 s = s[2:]
截断的前两个元素?
package main
import "fmt"
func main() {
s := []int{2, 3, 5, 7, 11, 13}
printSlice(s)
// 将切片切割为零长度。
s = s[:0]
printSlice(s)
// 扩展切片的长度。
s = s[:4]
printSlice(s)
// 删除前两个值。
s = s[2:]
printSlice(s)
}
func printSlice(s []int) {
fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}
点击运行按钮后,我们得到以下结果。
len=6 cap=6 [2 3 5 7 11 13]
len=0 cap=6 []
len=4 cap=6 [2 3 5 7]
len=2 cap=4 [5 7]
英文:
My question is about slice length and capacity. I'm learning about Go here: https://tour.golang.org/moretypes/11.
(My question was marked as a possible duplicate of this; however, this is not the case. My question is specifically about the cutting off the first few elements of a slice and the implications of that.)
Why does the line s = s[2:]
decrease the capacity when s = s[:4]
and s = s[:0]
do not? The only difference I see is that there is a number before the colon in s = s[2:]
while there is a number after the colon in the other two lines.
Is there any way to recover the first two elements that we cut off with s = s[2:]
?
package main
import "fmt"
func main() {
s := []int{2, 3, 5, 7, 11, 13}
printSlice(s)
// Slice the slice to give it zero length.
s = s[:0]
printSlice(s)
// Extend its length.
s = s[:4]
printSlice(s)
// Drop its first two values.
s = s[2:]
printSlice(s)
}
func printSlice(s []int) {
fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}
After clicking the Run button, we get the following.
len=6 cap=6 [2 3 5 7 11 13]
len=0 cap=6 []
len=4 cap=6 [2 3 5 7]
len=2 cap=4 [5 7]
答案1
得分: 30
你可以在这里阅读更多关于切片的内容:链接。但我认为这段话回答了你的问题:
“切片不会复制切片的数据。它创建一个指向原始数组的新切片值。这使得切片操作与操作数组索引一样高效。因此,修改重新切片的元素(而不是切片本身)会修改原始切片的元素。”
因此,如果你将切片赋值给同一个变量,你将无法恢复切片数据。
容量减少是因为通过删除前两个元素,你改变了指向新切片的指针(切片是通过指向第一个元素的指针引用的)。
make([]byte, 5)
s = s[2:4]
英文:
You can read more about slices here. But I think this passage answers your question:
> Slicing does not copy the slice's data. It creates a new slice value that points to the original array. This makes slice operations as efficient as manipulating array indices. Therefore, modifying the elements (not the slice itself) of a re-slice modifies the elements of the original slice.
So you cannot recover the slice data if you are assigning it to the same variable.
The capacity decrease is because by dropping the first 2 elements you are changing the pointer to the new slice (slices are referenced by the pointer to the first element).
How slices are represented in the memory:
make([]byte, 5)
s = s[2:4]
答案2
得分: 1
你可以使用完整的切片表达式:
package main
func main() {
s := []int{2, 3, 5, 7, 11, 13}
{ // 示例 1
t := s[:0]
println(cap(t) == 6)
}
{ // 示例 2
t := s[:0:0]
println(cap(t) == 0)
}
}
https://golang.org/ref/spec#Slice_expressions
英文:
You can use a full slice expression:
package main
func main() {
s := []int{2, 3, 5, 7, 11, 13}
{ // example 1
t := s[:0]
println(cap(t) == 6)
}
{ // example 2
t := s[:0:0]
println(cap(t) == 0)
}
}
答案3
得分: 0
slices.Clip
是 "golang.org/x/exp/slices"
中的一个函数,它可以通过完整切片表达式来减少切片的容量。
> Clip 函数会移除切片中未使用的容量,并返回 s[:len(s):len(s)]。
func main() {
s := []int{2, 3, 5, 7, 11, 13}
printSlice(s)
s = s[:4]
printSlice(s)
s = slices.Clip(s)
printSlice(s)
}
func printSlice(s []int) {
fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}
输出结果为:
len=6 cap=6 [2 3 5 7 11 13]
len=4 cap=6 [2 3 5 7]
len=4 cap=4 [2 3 5 7]
英文:
The slices.Clip
of "golang.org/x/exp/slices"
could reduce the capacity of slice through Full slice expressions.
> Clip removes unused capacity from the slice, returning s[:len(s):len(s)].
func main() {
s := []int{2, 3, 5, 7, 11, 13}
printSlice(s)
s = s[:4]
printSlice(s)
s = slices.Clip(s)
printSlice(s)
}
func printSlice(s []int) {
fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}
len=6 cap=6 [2 3 5 7 11 13]
len=4 cap=6 [2 3 5 7]
len=4 cap=4 [2 3 5 7]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论