Подтвердить что ты не робот

Как удалить элемент массива 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
}

Но всегда у меня ошибка "вне диапазона". Каков наилучший способ удаления элемента по ключу из массива структур?

4b9b3361

Ответ 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