我想从切片中删除一些元素,但这不起作用。
package main
import (
"fmt"
)
func main() {
a := []string{"a", "b", "c"}
for _, command := range a {
if command == "a" || command == "b" || command == "c" {
a = deleteSlice(a, command)
}
}
fmt.Println(a)
}
func deleteSlice(strings []string, str string) []string {
out := strings[:0]
for _, s := range strings {
if s != str {
out = append(out, s)
}
}
return out
}
预期结果是[]
,但实际上是[b]
。有人告诉我原因?
答案 0 :(得分:4)
该行为的 root 原因是在deleteSlice()
内,您没有分配新的支持数组,而是在重用传递给它的切片的支持数组,因为您在strings[:0]
中建立结果。
切片具有后备阵列。在您的代码中,初始化a
时,在包含以下元素的复合文字中,有一个分配给这种后备数组的单一分配:
array = ["a", "b", "c"]
因此首先使用其中的deleteSlice()
来调用"a"
,因此不会重新添加。第一次迭代后,支持数组如下所示:
array = ["b", "c", "c"]
[ ] <- returned out slice covers this
后备数组仍然包含3个元素,但切片仅覆盖前2个元素。
main中的循环进行到下一个迭代(索引= 1),循环遍历的切片覆盖整个支持数组(for rage
中使用的切片仅计算一次!),因此元素现在,后备数组中索引1处的位置为“ c”。这被传递到deleteSlice()
。 deleteSlice()
删除了"c"
元素,后备数组将不会更改("c"
之后没有要追加的元素):
array = ["b", "c", "c"]
[ ] <- returned out slice covers this
并且返回的切片的长度为1(后备数组的第一个元素。
main中的循环进行到最后一次迭代:index =2。支持数组在索引2处具有元素“ c”,该元素被传递到deleteSlice()
。该元素未包含在切片中(该切片包含单个["b"]
元素),因此将返回该元素。
查看相关问题:
Remove slice element within a for
建议的读数:
The Go Blog: Arrays, slices (and strings): The mechanics of 'append'