"
对于一个个人项目,我做了类似于这样的事情:
"
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 中不算不惯用,并且它避免了在调用端强制将切片分配到堆上。
container/list
提供的双向链表。 - mk12