我想以就地方式删除集合中的元素。 请考虑以下代码段:
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
)但更重要的是它会产生相同的结果。
答案 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
条款中。
第二个错误是xs
是Filter
函数的局部变量,所以如果你更改它所指向的内容(xs = ...
)不会改变{{1} }指向a
内部。您可以通过将其作为指针(main
,就像其他人发布的那样)或通过返回新的过滤切片来解决此问题,如下所示。
*xs