Delete element in a slice

func main() {
a := []string{"Hello1", "Hello2", "Hello3"}
fmt.Println(a)
// [Hello1 Hello2 Hello3]
a = append(a[:0], a[1:]...)
fmt.Println(a)
// [Hello2 Hello3]
}

How does this delete trick with the append function work?

It would seem that it's grabbing everything before the first element (empty array)

Then appending everything after the first element (position zero)

What does the ... (dot dot dot) do?

181642 次浏览

其中 a是片,i是要删除的元素的索引:

a = append(a[:i], a[i+1:]...)

...是 Go 中可变参数的语法。

基本上,当 定义一个函数它把所有的参数,你传递到一片该类型。通过这样做,您可以传递尽可能多的参数(例如,fmt.Println可以接受尽可能多的参数)。

现在,当 打来的 a 函数执行相反的操作: 它解压缩一个片,并将它们作为单独的参数传递给一个可变参数函数。

这条线是干什么的:

a = append(a[:0], a[1:]...)

本质上是:

a = append(a[:0], a[1], a[2])

现在,你可能想知道,为什么不只是做

a = append(a[1:]...)

append的函数定义是

func append(slice []Type, elems ...Type) []Type

所以第一个参数必须是正确类型的片段第二个参数是可变参数所以我们传入一个空片段然后解压缩其余片段来填充参数。

是可变参数的语法。

我认为它是由编译器使用 slice ([]Type),就像函数 append:

func append(slice []Type, elems ...Type) []Type

当您在“ append”中使用“ elems”时,实际上它是一个切片([]类型)。 所以“ a = append(a[:0], a[1:]...)”的意思是“ a = append(a[0:0], a[1:])

a[0:0]是一个什么都没有的片

a[1:]是“ Hello 2 Hello 3”

事情就是这样的

有两种选择:

答: 你关心的是保持数组顺序:

a = append(a[:i], a[i+1:]...)
// or
a = a[:i+copy(a[i:], a[i+1:])]

B: 你不在乎维持秩序(这样可能更快) :

a[i] = a[len(a)-1] // Replace it with the last one. CAREFUL only works if you have enough elements.
a = a[:len(a)-1]   // Chop off the last one.

如果您的数组是指针数组,请查看链接以查看内存泄漏的影响。

Https://github.com/golang/go/wiki/slicetricks

与其将 [a:]-、 [:b]-和 [a:b]-符号中的索引看作元素索引,不如将它们看作元素周围和元素之间的差距的索引,首先从 0的差距索引开始,然后再将元素索引为 0

enter image description here

只看蓝色的数字,就很容易看出发生了什么: [0:3]封闭了所有内容,[3:3]是空的,而 [1:2]将产生 {"B"}。那么 [a:]就是 [a:len(arrayOrSlice)]的简短版,[:b][0:b]的简短版,[:][0:len(arrayOrSlice)]的简短版。后者通常用于在需要时将数组转换为片。

我得到了一个超出范围的索引错误与公认的答案解决方案。 理由: 当范围开始时,它不是逐个迭代值,而是按索引迭代。 如果你修改一个切片,而它在范围内,它会引起一些问题。

老答案:

chars := []string{"a", "a", "b"}


for i, v := range chars {
fmt.Printf("%+v, %d, %s\n", chars, i, v)
if v == "a" {
chars = append(chars[:i], chars[i+1:]...)
}
}
fmt.Printf("%+v", chars)

预期:

[a a b], 0, a
[a b], 0, a
[b], 0, b
Result: [b]

实际情况:

// Autual
[a a b], 0, a
[a b], 1, b
[a b], 2, b
Result: [a b]

正确的方法(解决方法) :

chars := []string{"a", "a", "b"}


for i := 0; i < len(chars); i++ {
if chars[i] == "a" {
chars = append(chars[:i], chars[i+1:]...)
i-- // form the remove item index to start iterate next item
}
}


fmt.Printf("%+v", chars)

资料来源: https://dinolai.com/notes/golang/golang-delete-slice-item-in-range-problem.html

虽然不是一种优雅的方法,但它确实有效

    var a = []string{"a", "b", "c", "d"}
str := strings.Join(a, `,`)
str2 := "a" // element to be removed


arr := strings.Split(strings.Trim(strings.Replace(str, str2, "", -1), ","), ",")

假设你那一份的价值是这样的: [9 3 7 11 4 12 16 19 4]

删除7和11元素

x = append(x[:2], x[4:]...)

结果就是:

[9 4 12 16 19 4]

希望能帮上忙!