删除Golang切片元素

时间:2014-07-14 09:33:19

标签: go slice in-place

我想以就地方式删除集合中的元素。 请考虑以下代码段:

package main

import "fmt"

type Ints []int

func (xs Ints) Filter() {
    for i := 0; i < len(xs); i++ {
        if xs[i]%2 == 0 { // Or some other filtering function
             xs = append(xs[:i], xs[i+1:]...)
        }
        fmt.Printf("i %+v\n", i)
        fmt.Printf("xs %+v\n", xs)
    }
}

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

    fmt.Printf("initial a %+v\n", a)

    a.Filter()

    fmt.Printf("final a %+v\n", a)
}

http://play.golang.org/p/1nL6Il2Gf1

令人惊讶的结果是:final a [1 3 5 7 9 10 10 10 10 10]

我想知道该怎么做。我非常确定接收器需要是Ints的指针。但这会稍微混淆代码(可能在括号中添加*xs)但更重要的是它会产生相同的结果。

3 个答案:

答案 0 :(得分:3)

我通过移动元素,然后调整切片大小以及使用指针来实现。像这样:

package main

import "fmt"

type Ints []int

func (xs *Ints) Filter() {
    filterPos := 0
    for i := 0; i < len(*xs); i++ {
        if (*xs)[i]%2 == 0 { // Or some other filtering function
             (*xs)[filterPos] = (*xs)[i]
         filterPos++
        }
    }
    (*xs) = (*xs)[:filterPos]
}

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

    fmt.Printf("initial a %+v\n", a)

    a.Filter()

    fmt.Printf("final a %+v\n", a)
}

答案 1 :(得分:1)

你必须在这里使用指针。如果您不喜欢在每个只使用临时变量来执行所有操作的地方添加* xs,那么请将其设置回来。这是代码http://play.golang.org/p/eAFkV3Lwh6

答案 2 :(得分:1)

您的代码几乎是正确的。

第一个错误是,当您删除元素时,您需要避免执行i++,否则i++会跳过下一个未读元素。这就是为什么我把它放在else条款中。

第二个错误是xsFilter函数的局部变量,所以如果你更改它所指向的内容(xs = ...)不会改变{{1} }指向a内部。您可以通过将其作为指针(main,就像其他人发布的那样)或通过返回新的过滤切片来解决此问题,如下所示。

*xs

http://play.golang.org/p/Nre7w4KQ78