Ruby:在使用该对象循环遍历列表时删除对象

Ruby: deleting object while looping over list with that object

所以我有多个列表来跟踪 2D 游戏中的对象,但如果这些对象离开屏幕,我想删除这些对象,以便它们不再更新。我下面的内容对我有用,但这不适用于其他语言。通常我必须制作另一个 "destroy list" 来保存我想要销毁的对象,然后再次循环以删除它们,因为您无法在迭代时从列表中删除对象而不会出现一些明显的故障。

是 Ruby 只是在执行此操作时没有显示任何可见故障,还是 Ruby 的数组在仍在迭代时从列表中删除多个可能的对象时工作方式不同?

objects = []

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

在 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. 计数 = 1
  4. 3(对象的长度)> 1
  5. 第 3 号已生成并删除。
  6. 计数 = 2
  7. 2(对象的长度)不大于count
  8. 我们已经完成了,所以我们有 [2, 4]

使用 delete_if:

有更好的方法来完成您正在尝试的事情
new_objects = objects.delete_if {|o| o.withinBounds }