Как безопасно удалить элементы из фрагмента, так как количество элементов в фрагменте меняется - PullRequest
0 голосов
/ 08 ноября 2018

После того, как я переберу слайс пользователя, мне нужно удалить некоторых пользователей из слайса на основании некоторого условия. Я буду многократно повторять этот пользовательский фрагмент, медленно удаляя некоторые элементы.

Я знаю, что из других языков небезопасно удалять элементы из коллекции во время зацикливания. Поэтому я сохраняю элементы, которые я хочу удалить, на карте toMutate. Как только мой первоначальный цикл закончен, я продолжаю и пытаюсь удалить элементы из среза.

toMutate := make(map[int]User, 100)
for idx, u := range c.users {
  if someCondition {
    toMutate[idx] = u
  }
}

Затем я вызываю эту функцию, чтобы удалить элементы из среза пользователя.

for idx, u := range toMutate {
  c.users = append(c.users[:idx], c.users[idx+1:]...)
}

Теперь я получаю сообщение об ошибке:

паника: ошибка времени выполнения: границы среза выходят за пределы диапазона

Кажется, я знаю, почему я получаю ошибку. На каждой итерации я удаляю элемент из среза. Так что теперь мое значение idx отключено, так как количество элементов изменилось.

Как вы справляетесь с такими ситуациями?

Ответы [ 2 ]

0 голосов
/ 08 ноября 2018

Я думаю, что это более эффективно, чем удерживать его на карте и повторно разрезать для каждого значения, которое нужно удалить.

func updateUser(users []User) []User {

    temp := make([]User, 0, len(users))

    for _, u := range users {
        if !condition(u) {
            temp = append(temp, u)
        }
    }
    return temp
}

Но что-то, что было бы лучше, - это использовать какую-то другую структуру данных, например, связанный список или что-то, что оптимизировано для удалений.

Массивы (фрагменты) не эффективны для удаления элементов между ними.

0 голосов
/ 08 ноября 2018

Идея родов выглядит следующим образом:

toMutate := []int {}
for idx := range c.users {
    if someCondition {
        toMutate = append(toMutate, idx)
    }
}
//...
sort.Sort(sort.Reverse(sort.IntSlice(toMutate)))
//...
for _, u := range toMutate {
   c.users = append(c.users[:u], c.users[u+1:]...)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...