从切片中删除元素不起作用

时间:2019-11-26 10:41:33

标签: arrays go slice

我想从切片中删除一些元素,但这不起作用。

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]。有人告诉我原因?

1 个答案:

答案 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

Remove elements in slice

建议的读数:

The Go Blog: Arrays, slices (and strings): The mechanics of 'append'

The Go Blog: Go Slices: usage and internals

Go Wiki: Slice tricks