Для личного проекта я сделал что-то вроде этого:
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]
}
(Примечание: не проверено.)
Нет выделений, ничего сложного, иИсходя из приблизительного размера списка записей и списка идентификаторов, которые вы представили, простой линейный поиск, скорее всего, подойдет, как и более интересные вещи, но без каких-либо накладных расходов.Я понимаю, что моя версия изменяет слайс , а возвращает новый слайс, но это не лишает смысла в Go, и это позволяет избежать принудительного выделения слайса в месте вызова для выделения кучи.