Удалить записи из фрагмента, итерации над ним в Go
Каков наилучший способ удаления элементов из среза во время его изменения?
Например:
type MultiDataPoint []*DataPoint
func (m MultiDataPoint) Json() ([]byte, error) {
for i, d := range m {
err := d.clean()
if ( err != nil ) {
//Remove the DP from m
}
}
return json.Marshal(m)
}
Ответы
Ответ 1
Как вы уже упоминали в другом месте, вы можете выделить новый блок памяти и скопировать в него только действительные элементы. Однако, если вы хотите избежать выделения, вы можете переписать свой фрагмент на месте:
i := 0 // output index
for _, x := range s {
if isValid(x) {
// copy and increment index
s[i] = x
i++
}
}
s = s[:i]
Полный пример: http://play.golang.org/p/FNDFswPeDJ
Обратите внимание, что он оставит некоторый мусор после индекса i
в базовом массиве, поэтому убедитесь, что в нем нет других срезов.
Ответ 2
Там могут быть лучшие способы, но вот пример, который удаляет четные значения из среза:
m := []int{1,2,3,4,5,6}
deleted := 0
for i := range m {
j := i - deleted
if (m[j] & 1) == 0 {
m = m[:j+copy(m[j:], m[j+1:])]
deleted++
}
}
Обратите внимание, что я не получаю элемент с использованием синтаксиса i, d := range m
, так как d
в конечном итоге будет настроен на неправильные элементы после того, как вы начнете удаление из среза.
Ответ 3
Я знаю, что его ответ давно, но я использую что-то подобное на других языках, но я не знаю, является ли это способом golang.
Просто перебирайте назад, чтобы вам не приходилось беспокоиться об удаленных индексах. Я использую тот же пример, что и Адам.
m = []int{3, 7, 2, 9, 4, 5}
for i := len(m)-1; i >= 0; i-- {
if m[i] < 5 {
m = append(m[:i], m[i+1:]...)
}
}
Ответ 4
Другим вариантом является использование цикла normal для использования длины среза и вычитания 1 из индекса каждый раз при удалении значения. См. Следующий пример:
m := []int{3, 7, 2, 9, 4, 5}
for i := 0; i < len(m); i++ {
if m[i] < 5 {
m = append(m[:i], m[i+1:]...)
i-- // -1 as the slice just got shorter
}
}
Я не знаю, использует ли len()
достаточное количество ресурсов, но вы также можете запустить его только один раз и вычесть из значения длины:
m := []int{3, 7, 2, 9, 4, 5}
for i, s := 0, len(m); i < s; i++ {
if m[i] < 5 {
m = append(m[:i], m[i+1:]...)
s--
i--
}
}
Ответ 5
Что-то вроде:
m = append(m[:i], m[i+1:]...)
Ответ 6
Вам даже не нужно считать в обратном направлении, но вам нужно проверить, что вы находитесь в конце массива, где предложенный метод append()
завершится неудачно. Вот пример удаления повторяющихся положительных целых чисел из отсортированного списка:
// Remove repeating numbers
numbers := []int{1, 2, 3, 3, 4, 5, 5}
log.Println(numbers)
for i, numbersCount, prevNum := 0, len(numbers), -1; i < numbersCount; numbersCount = len(numbers) {
if numbers[i] == prevNum {
if i == numbersCount-1 {
numbers = numbers[:i]
} else {
numbers = append(numbers[:i], numbers[i+1:]...)
}
continue
}
prevNum = numbers[i]
i++
}
log.Println(numbers)
Детская площадка: https://play.golang.org/p/v93MgtCQsaN
Ответ 7
Попробуйте сортировку и бинарный поиск.
Пример:
package main
import (
"fmt"
"sort"
)
func main() {
// Our slice.
s := []int{3, 7, 2, 9, 4, 5}
// 1. Iterate over it.
for i, v := range s {
func(i, v int) {}(i, v)
}
// 2. Sort it. (by whatever condition of yours)
sort.Slice(s, func(i, j int) bool {
return s[i] < s[j]
})
// 3. Cut it only once.
i := sort.Search(len(s), func(i int) bool { return s[i] >= 5 })
s = s[i:]
// That it!
fmt.Println(s) // [5 7 9]
}
https://play.golang.org/p/LnF6o0yMJGT
Ответ 8
Я просто реализую метод, который удаляет все нулевые элементы в слайсе.
И я использовал его для решения проблем с Leetcode, он отлично работает.
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func removeNil(lists *[]*ListNode) {
for i := 0; i < len(*lists); i++ {
if (*lists)[i] == nil {
*lists = append((*lists)[:i], (*lists)[i+1:]...)
i--
}
}
}
Ответ 9
Вот более идиоматичный способ удаления элементов из фрагментов.
temp := s[:0]
for _, x := range s {
if isValid(x) {
temp = append(temp, x)
}
}
s = temp
Ссылка на игровую площадку: https://play.golang.org/p/OH5Ymsat7s9
Примечание: ссылки на примеры и игровые площадки основаны на ответе @tomasz fooobar.com/info/544385/...