func main() {
a := []string{"Hello1", "Hello2", "Hello3"}
fmt.Println(a)
// [Hello1 Hello2 Hello3]
a = append(a[:0], a[1:]...)
fmt.Println(a)
// [Hello2 Hello3]
}
Run Code Online (Sandbox Code Playgroud)
这个删除技巧如何与append函数一起工作?
似乎它在第一个元素(空数组)之前抓住了所有东西
然后在第一个元素(位置零)之后追加所有内容
......(点点)是做什么的?
dav*_*ave 268
a切片在哪里,并且i是要删除的元素的索引:
a = append(a[:i], a[i+1:]...)
Run Code Online (Sandbox Code Playgroud)
... 是Go中可变参数的语法.
基本上,在定义函数时,它会将您传递的所有参数放入该类型的一个切片中.通过这样做,您可以根据需要传递任意数量的参数(例如,fmt.Println可以根据需要使用尽可能多的参数).
现在,在调用函数时,...执行相反的操作:它解压缩一个切片并将它们作为单独的参数传递给一个可变参数函数.
那么这一行是做什么的:
a = append(a[:0], a[1:]...)
Run Code Online (Sandbox Code Playgroud)
基本上是:
a = append(a[:0], a[1], a[2])
Run Code Online (Sandbox Code Playgroud)
现在,你可能想知道,为什么不做
a = append(a[1:]...)
Run Code Online (Sandbox Code Playgroud)
好吧,功能定义append是
func append(slice []Type, elems ...Type) []Type
Run Code Online (Sandbox Code Playgroud)
所以第一个参数必须是正确类型的一个切片,第二个参数是可变参数,所以我们传入一个空切片,然后解压缩切片的其余部分以填充参数.
Chr*_*ris 42
有两种选择:
答:您关心保留数组顺序:
a = append(a[:i], a[i+1:]...)
// or
a = a[:i+copy(a[i:], a[i+1:])]
Run Code Online (Sandbox Code Playgroud)
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.
Run Code Online (Sandbox Code Playgroud)
如果您的数组是指针,请参阅链接以查看内存泄漏的含义.
https://github.com/golang/go/wiki/SliceTricks
Zyl*_*Zyl 10
不要将[a:]-,[:b]-和- [a:b]标记中的索引视为元素索引,而应将它们视为元素周围和元素之间的间隙的索引,从0在元素索引为之前的间隙索引开始0。
仅查看蓝色数字,就更容易了解发生了什么:将[0:3]所有内容围起来,[3:3]为空并[1:2]产生yield {"B"}。然后[a:]是的短版[a:len(arrayOrSlice)],[:b]的短版[0:b]和[:]的短版[0:len(arrayOrSlice)]。后者通常用于在需要时将数组变成切片。
...是可变参数的语法.
我认为它是由编译器使用slice实现的([]Type)就像函数append:
func append(slice []Type, elems ...Type) []Type
Run Code Online (Sandbox Code Playgroud)
当你在"追加"中使用"elems"时,实际上它是一个切片([]类型).所以" a = append(a[:0], a[1:]...)"的意思是" a = append(a[0:0], a[1:])"
a[0:0] 是一片什么都没有
a[1:] 是"Hello2 Hello3"
这是它的工作原理
小智 5
我在接受的答案解决方案中得到一个索引超出范围的错误。原因:range start时不是一一迭代value,而是index迭代。如果在范围内修改切片,则会引发一些问题。
旧答案:
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)
Run Code Online (Sandbox Code Playgroud)
预期的 :
[a a b], 0, a
[a b], 0, a
[b], 0, b
Result: [b]
Run Code Online (Sandbox Code Playgroud)
实际的:
// Autual
[a a b], 0, a
[a b], 1, b
[a b], 2, b
Result: [a b]
Run Code Online (Sandbox Code Playgroud)
正确方法(解决方案):
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)
Run Code Online (Sandbox Code Playgroud)
来源:https : //dinolai.com/notes/golang/golang-delete-slice-item-in-range-problem.html
| 归档时间: |
|
| 查看次数: |
158076 次 |
| 最近记录: |