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) }
делается:
- Начнем с 4 (длина объектов) > 0.
- Номер 1 получен и удален.
- count = 1
- 3 (длина объектов) > 1
- Номер 3 получен и удален.
- count = 2
- 2 (длина объектов) не больше чем количество
- Мы сделали, поэтому у нас есть
[2, 4]
Есть лучший способ сделать то, что вы пытаетесь, используя delete_if:
new_objects = objects.delete_if {|o| o.withinBounds }