Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Golang在迭代切片时删除元素_Go_Slice - Fatal编程技术网

Golang在迭代切片时删除元素

Golang在迭代切片时删除元素,go,slice,Go,Slice,我想从切片中删除一些元素,并建议此切片操作: a=append(a[:i],a[i+1:]…) 然后我编码如下: package main import ( "fmt" ) func main() { slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9} for i, value := range slice { if value%3 == 0 { // remove 3, 6, 9 slice =

我想从切片中删除一些元素,并建议此切片操作:

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

然后我编码如下:

package main

import (
    "fmt"
)

func main() {
    slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
    for i, value := range slice {
        if value%3 == 0 { // remove 3, 6, 9
            slice = append(slice[:i], slice[i+1:]...)
        }
    }
    fmt.Printf("%v\n", slice)
}
随着
go run hello.go
,它会感到恐慌:

panic: runtime error: slice bounds out of range

goroutine 1 [running]:
panic(0x4ef680, 0xc082002040)
    D:/Go/src/runtime/panic.go:464 +0x3f4
main.main()
    E:/Code/go/test/slice.go:11 +0x395
exit status 2
如何更改此代码以正确执行?

我尝试了以下方法:

首先,用一个
goto
语句:

func main() {
    slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
Label:
    for i, n := range slice {
        if n%3 == 0 {
            slice = append(slice[:i], slice[i+1:]...)
            goto Label
        }
    }
    fmt.Printf("%v\n", slice)
}
这是可行的,但是迭代太多了

第二,使用另一个共享同一备份阵列的切片:

func main() {
    slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
    dest := slice[:0] 
    for _, n := range slice {
        if n%3 != 0 { // filter
            dest = append(dest, n)
        }
    }
    slice = dest
    fmt.Printf("%v\n", slice)
}
但不确定这一个是否更好

第三,从,带
len
操作员:

func main() {
    slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
    for i := 0; i < len(slice); i++ {
        if slice[i]%3 == 0 {
            slice = append(slice[:i], slice[i+1:]...)
            i-- // should I decrease index here?
        }
    }
    fmt.Printf("%v\n", slice)
}
func main(){
切片:=[]int{1,2,3,4,5,6,7,8,9}
对于i:=0;i
我现在该选哪一个

基准:

func BenchmarkRemoveSliceElementsBySlice(b *testing.B) {
    for i := 0; i < b.N; i++ {
        slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
        dest := slice[:0]
        for _, n := range slice {
            if n%3 != 0 {
                dest = append(dest, n)
            }
        }
    }
}

func BenchmarkRemoveSliceElementByLen(b *testing.B) {
    for i := 0; i < b.N; i++ {
        slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
        for i := 0; i < len(slice); i++ {
            if slice[i]%3 == 0 {
                slice = append(slice[:i], slice[i+1:]...)
            }
        }
    }
}


$ go test -v -bench=".*"
testing: warning: no tests to run
PASS
BenchmarkRemoveSliceElementsBySlice-4   50000000                26.6 ns/op
BenchmarkRemoveSliceElementByLen-4      50000000                32.0 ns/op
func benchmarkremoveslicelementsbyslice(b*testing.b){
对于i:=0;i

似乎删除一个循环中的所有元素更好

迭代要保留的切片复制元素

k := 0
for _, n := range slice {
    if n%3 != 0 { // filter
        slice[k] = n
        k++
    }
}
slice = slice[:k] // set slice len to remaining elements
切片技巧在删除单个元素的情况下非常有用。如果可能会删除多个元素,则使用上面的for循环


这是一个很好的小片段回答:

package main

import "fmt"

func main() {
    slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}

    k := 0
    for _, n := range slice {
        if n%3 != 0 { // filter
            slice[k] = n
            k++
        }
    }
    slice = slice[:k]

    fmt.Println(slice) //[1 2 4 5 7 8]
}
对于最小化第一个元素(对于大片)的内存写入,可以使用以下方法:

package main

import "fmt"

func main() {
    slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}

    k := 0
    for i, n := range slice {
        if n%3 != 0 { // filter
            if i != k {
                slice[k] = n
            }
            k++
        }
    }
    slice = slice[:k]

    fmt.Println(slice) //[1 2 4 5 7 8]
}
如果需要新切片保留旧切片

package main

import "fmt"

func main() {
    slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}

    s2 := make([]int, len(slice))
    k := 0
    for _, n := range slice {
        if n%3 != 0 { // filter
            s2[k] = n
            k++
        }
    }
    s2 = s2[:k]

    fmt.Println(s2) //[1 2 4 5 7 8]
}

除此之外,像这样迭代整个数组并填充一个新数组更有效。如果您在这里使用简单的primative,您实际上可以通过预测获得硬件性能增益。阅读有关编码的“机械同情”,特别是在围棋中,以利用CPU算法。虽然你的基准测试在9个数字上可能没有多少收益,但试着用几百万看看收益。你用这个救了我。