对于一个个人项目,我做了这样的事情:
func filter(sl []int, fn func(int) bool) []int {
result := make([]int, 0, len(sl))
last := 0
for i, v := range sl {
if fn(v) {
result = append(result, sl[last:i]...)
last = i + 1
}
}
return append(result, sl[last:]...)
}
它不会改变原始的,但应该是相对有效的。
这样做可能会更好:
func filter(sl []int, fn func(int) bool) (result []int) {
for _, v := range sl {
if !fn(v) {
result = append(result, v)
}
}
return
}
更简单、更干净。
如果你想就地做,你可能想要这样的东西:
func filter(sl []int, fn func(int) bool) []int {
outi := 0
res := sl
for _, v := range sl {
if !fn(v) {
res[outi] = v
outi++
}
}
return res[0:outi]
}
您可以优化它以使用 copy 复制元素范围,但这是两次
代码,可能不值得。
因此,在这种特定情况下,我可能会这样做:
func deleteRecords(l []*Record, ids []int) []*Record {
outi := 0
L:
for _, v := range l {
for _, id := range ids {
if v.id == id {
continue L
}
}
l[outi] = v
outi++
}
return l[0:outi]
}
(注:未经测试。)
没有分配,没有什么花哨的,并且假设记录列表和您提供的 id 列表的粗略大小,简单的线性搜索可能会做得更好,但没有任何开销。我意识到我的版本改变了切片 并且 返回一个新切片,但这在 Go 中并不是惯用的,它避免了强制调用站点上的切片进行堆分配。