Ruby的“每个”方法不会遍历数组中的所有项目?

时间:2013-05-10 08:09:29

标签: ruby loops each

我正在尝试以下代码:

a = [1,2,3,4]  
a.each do  
  puts "Removing #{a.last}"  
  a.pop  
end

但是没有弹出所有四个数字,我只得到第一个3.确实,做一些像放置a.length的东西返回1并且放置它显示元素“1”仍然存在。

我如何正确使用该方法? (我使用的是Ruby 2.0)。

6 个答案:

答案 0 :(得分:6)

我怀疑这种情况正在发生,因为你在修改列表的同时迭代列表中的元素。

尝试以下方法:

a = [1,2,3,4]
until a.empty? do
  puts "Removing #{a.last}"
  a.pop
end

答案 1 :(得分:3)

<强>问题
在迭代a时,你正在改变它。

问题解释
这意味着一旦删除了一个元素,每个方法都会被抛弃,因为突然元素a包含的数量会少一个。因此索引也被抛弃了 如果我执行此操作:

a = [1,2,3,4]
a.each do
  |thing| 
  puts thing
  a.delete(thing)
end

我将获得输出[1,3]。 那是因为发生了以下情况:
在从索引0的列表中删除1之前,2在索引1处。 删除1之后,2处于索引0而不是1,因此2不是迭代的下一个元素,而是3!

顺便说一下你可以像我用thing那样定义一个本地块变量来访问你迭代的每个元素。

<强>解决方案
为了得到你想要的东西,你需要创建一个副本并进行处理。

 a = [1,2,3,4]
 b = a.clone
 a.each do
   |thing|
   puts thing
   b.delete(thing)
 end

现在,当你迭代它并改变b时,它仍然是相同的。 因此,在此循环结束时a = [1,2,3,4]b =[] 在您说a = b之后,您将获得所需的结果。

当然您可以根据背面的弹出元素进行调整。只需确保处理副本,这样就不会在迭代时更改元素。

答案 2 :(得分:2)

其他一些答案说明了为什么你的代码不起作用。

另一种方法是这样做(假设nil中没有falsea):

a = [1,2,3,4]
while e = a.pop
  puts "Removing #{e}"
end

答案 3 :(得分:1)

查看输出,这清楚地表明为什么你们每个人都没有运行所有的数组元素。由于你是pop(ing)Array#pop,所以删除了最后一个元素。当每个传递2到块时,原始数组a变为空,因此each停止迭代。:

a = [1,2,3,4]  
a.each do |i| 
  puts i
  puts "Removing #{a.last}"  
  p a.pop  
  p "========"
end

输出:

1
Removing 4
4
"========"
2
Removing 3
3
"========"

所以你可以使用下面的内容:

a = [1,2,3,4]  
(0...a.size).each do |i|
p a.pop
end

输出:

4
3
2
1

答案 4 :(得分:0)

a = [1,2,3,4]  
a.length.times do  
  puts "Removing #{a.last}"  
  a.pop  
end

答案 5 :(得分:0)

试试这个:

a.count.times do a.pop and puts "Removing #{a.last + 1 rescue 1}" end

在do循环中应该这样做