Ruby: удаление объекта при зацикливании списка с этим объектом

Поэтому у меня есть несколько списков для отслеживания объектов в 2D-игре, но если эти объекты исчезают с экрана, я хочу удалить эти объекты, чтобы они больше не обновлялись. То, что я имею ниже, работает для меня, но это не работает на других языках. Обычно мне приходится создавать еще один "список уничтожения", в котором сохраняются объекты, которые я хочу уничтожить, а затем повторяю цикл, чтобы удалить их, потому что вы не можете удалить объект из списка, выполняя итерацию без какого-либо видимого сбоя.

Ruby просто не показывает никаких видимых сбоев при выполнении этого или массив Ruby работает по-разному, удаляя несколько возможных объектов из списка, пока он еще итерирует?

objects = []

objects.each{|o| o.withinBounds ? o.update : objects.delete(o)}

1 ответ

Решение

В Ruby вы действительно найдете сбой, если будете делать то, что говорите.

Попробуй это:

objects = [1,2,3,4]
objects.each { |el| objects.delete(el) }
=> [2, 4]

Можно ожидать, что результатом будет пустой массив, но это не так. Мы запутались с элементами arr а также each запутывается, потому что длина массива изменилась. Каждый итератор выглядит примерно так в псевдокоде:

count = 0
while length(objects) > count
  yield objects[count]
  count + 1
end

Итак, в приведенном выше примере причина, почему мы получаем [2, 4] можно объяснить пошаговый анализ того, что objects.each { |el| objects.delete(el) } делается:

  1. Начнем с 4 (длина объектов) > 0.
  2. Номер 1 получен и удален.
  3. count = 1
  4. 3 (длина объектов) > 1
  5. Номер 3 получен и удален.
  6. count = 2
  7. 2 (длина объектов) не больше чем количество
  8. Мы сделали, поэтому у нас есть [2, 4]

Есть лучший способ сделать то, что вы пытаетесь, используя delete_if:

new_objects = objects.delete_if {|o| o.withinBounds }
Другие вопросы по тегам