Ruby在迭代时删除数组元素

时间:2017-09-08 12:26:15

标签: ruby

a = ['red', 'green', 'blue', 'purple']

a.each do |e|
 puts e
 if e == 'green'
  a.delete(e)
 end
end

通过运行上面的代码,我得到以下输出:

red
green
purple

有人可以向我解释幕后发生的事情吗?

2 个答案:

答案 0 :(得分:6)

这是[{1}}

的实施的一部分
each

所以它只是简单地移动一个"阅读头"沿阵列直到它到达终点。

当您删除for (i=0; i<RARRAY_LEN(ary); i++) { rb_yield(RARRAY_AREF(ary, i)); } return ary; 时,数组的元素会移动以取代它,而"green"现在是绿色的位置。但是我们已经在这个位置读取了元素。要读取的下一个元素是紫色。

这就是为什么你永远不应该改变你正在迭代的集合(除非这个效果是你真正想要的)。

  

我无法理解原生代码

这里有一点可视化&#34;阅读头&#34;心理模型。

"blue"

答案 1 :(得分:3)

为了补充塞尔吉奥的解释,修改数组的更惯用的方法是:

a = ['red', 'green', 'blue', 'purple']
a.reject! do |e|
  puts e
  e == 'green'
end

这样:

2.2.5 :001 >     a = ['red', 'green', 'blue', 'purple']
 => ["red", "green", "blue", "purple"] 
2.2.5 :002 >     a.reject! do |e|
2.2.5 :003 >           puts e
2.2.5 :004?>         e == 'green'
2.2.5 :005?>       end
red
green
blue
purple
 => ["red", "blue", "purple"] 
2.2.5 :006 >