2013-01-18 50 views
2

我是新来的Ruby和我写了一个非常简单的应用程序打印一周的天数,然后在循环中删除一个天:为什么Array.each中的Array.delete不会删除所有项目?

def print_days(days) 
    days.each do |day| 
     print "The day of the week is: #{day}\n" 
     days.delete(day) 
     print "\n*****************************************************\n" 
     print days 
     print "\n*****************************************************\n" 
    end 
end 

wd = %w[Monday Tuesday Wednesday Thursday Friday Saturday Sunday] 

print print_days(wd 

这让下面的输出时运行。任何人都可以解释为什么当我按顺序删除每个元素时为什么会跳过星期二,星期四和星期六,并且数组显示它们在那里?您可以在安装运行这个简单的代码:

The day of the week is: Monday 

***************************************************** 
["Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] 
***************************************************** 
The day of the week is: Wednesday 

***************************************************** 
["Tuesday", "Thursday", "Friday", "Saturday", "Sunday"] 
***************************************************** 
The day of the week is: Friday 

***************************************************** 
["Tuesday", "Thursday", "Saturday", "Sunday"] 
***************************************************** 
The day of the week is: Sunday 

***************************************************** 
["Tuesday", "Thursday", "Saturday"] 
***************************************************** 
["Tuesday", "Thursday", "Saturday"] 
+2

你为什么要叫''each'内delete'?你试图达到什么目的? –

+1

(请尝试创建一个重点标题。) – 2013-01-18 21:06:02

回答

4

你从数组删除元素,而你是通过它迭代,无效的迭代器。

你可以尝试

until (days.empty?) 
     day = days.shift 
     print "The day of the week is: #{day}\n" 
    end 

days.each{|day| print "The day of the week is: #{day}\n"} 
    days.clear 
+0

应该使用“shift”而不是'unshift'吗? –

+1

是的,哎呀。固定。 – AShelly

+0

有点帮助。非常感谢!我有一个问题,当我迭代使用array.each是不一样的迭代使用'直到'?直到调用迭代器? –

3

你的所有元素的迭代过程中修改阵列。在内部,每种方法都会保留它所产生的最后一项的索引。这基本上使迭代器无效。其他语言会为您抛出异常。

Ruby没有。

所以在第一次通过它产生元素索引0处

然后就通过在下一时间索引0

然后删除元素它产生元素的索引为1,这基本上跳过星期二,因为它现在在索引0.

+0

是的,那是一个错误! –

2

你打破了基本规则,不要改变你正在迭代的对象,而你正在迭代它!

这里什么happeneing:数组

  • 开始第一个项目
  • 删除的第一个项目
  • 数组中的第二个项目是目前第一

    1. 迭代。
    2. 抓住第二个项目,既然前面的第二个项目现在是第一个,它抓住了原来的第三个项目。
    3. 突变的阵列

    所以这样的跳过删除所有其他项目中删除所述第二项目(其曾经是三分之一)。这些奇怪的错误类型是为什么当你迭代它时改变你正在迭代的对象是非常不被接受的。不要这样做。

    但是考虑到你的例子有多么人为,很难提出更好的方法。根据您的实际目标,有更好的方法来做到这一点。

  • +0

    我认为基本规则“从未卷入亚洲的地面战争”,其次是“死亡时不要与西西里人对抗” –

    +1

    在迭代时突变数组? _不可思议!_ –

    0

    鉴于上述大部分答案的解释你为什么这样做失败的东西,你可以得到你似乎什么用的

    Array#drop_while 
    Array#delete_if 
    Array#select! 
    

    Array#keep_if 
    

    例如变化想

    a=[1,2,3,4] 
    a.drop_while{|e| puts e; true} 
    

    给人

    1 
    2 
    3 
    4 
    => [] 
    
    相关问题