Как удалить элемент массива struct в цикле в golang
Проблема
У меня есть массив структур:
type Config struct {
Applications []Application
}
Примечание. Config - это структура для json.Decode.
config = new(Config)
_ = decoder.Decode(&config)
В цикле у меня есть некоторое условие и удаление элемента по ключу.
for i, application := range config.Applications {
if i == 1 {
config.Applications = _removeApplication(i, config.Applications)
}
}
func _removeApplication(i int, list []Application) []Application {
if i < len(list)-1 {
list = append(list[:i], list[i+1:]...)
} else {
log.Print(list[i].Name)
list = list[:i]
}
return list
}
Но всегда у меня ошибка "вне диапазона". Каков наилучший способ удаления элемента по ключу из массива структур?
Ответы
Ответ 1
Цитата из страницы Slice Tricks, удаляющей элемент по индексу i
:
a = append(a[:i], a[i+1:]...)
// or
a = a[:i+copy(a[i:], a[i+1:])]
Обратите внимание, что если вы планируете удалять элементы из среза, который вы сейчас зацикливаете, это может вызвать проблемы. И это происходит, если элемент, который вы удаляете, является текущим (или предыдущий элемент уже зациклирован), поскольку после удаления все последующие элементы сдвигаются, но цикл range
не знает об этом и все равно увеличит индекс, и вы пропустите один элемент.
Вы можете избежать этого, используя нисходящий цикл:
for i := len(config.Applications) - 1; i >= 0; i-- {
application := config.Applications[i]
// Condition to decide if current element has to be deleted:
if haveToDelete {
config.Applications = append(config.Applications[:i],
config.Applications[i+1:]...)
}
}
Ответ 2
Вы получаете эту ошибку, потому что выполняете цикл над срезом с внутренним диапазоном длины X, который стал X-n, потому что вы удаляете некоторые элементы во время цикла.
Если вы хотите удалить элемент из определенного индекса из среза, вы можете сделать это следующим образом:
sliceA = append(sliceA[:indexOfElementToRemove], sliceA[indexOfElementToRemove+1:]...)
Ответ 3
Этот вопрос немного старше, но я не нашел другого ответа на StackOverflow, в котором упоминается следующий трюк из Slice Tricks для фильтрации списка:
b := a[:0]
for _, x := range a {
if f(x) {
b = append(b, x)
}
}
Итак, в этом случае функция, которая удаляет определенные элементы, может выглядеть так:
func removeApplications(apps []Applications) []Applications {
filteredApps := apps[:0]
for _, app := apps {
if !removeApp {
filteredApps = append(filteredApps, app)
}
}
return filteredApps
}
Ответ 4
Я думаю, что простой способ
var (
slice = []int{1,2,3,4,5}
pos int
)
for _, i := range slice {
if i == 3 {
slice = append(slice[:pos], slice[pos+1:]...)
if pos > 0 {
pos = pos - 1
}
continue
}
pos++
}
здесь...
https://play.golang.org/p/pK3B5Mii9k