3

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

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

objects = []

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

1 回答 1

4

在 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 }
于 2017-08-05T22:22:04.283 回答