这是 Ruby Programming 第十一章的一个练习,讲的是如何在不新建数组的情况下,取出 3 的倍数。程序如下,但发现 list.delete 总不能如期删除 非 3 的倍数。
list = []
for i in 0...100
list[i]=i+1;
end
list.each{|i|
if ((i % 3) != 0) then
list.delete(i)
end
}
p list
首先,多行 block 不要用{}而要用 do..end。单行才用{}
list = []
for i in 0...100
list[i]=i+1;
end
list.each do |i|
if ((i % 3) != 0) then
list.delete(i)
end
end
p list
然后你在 block 里修改了对象,就相当容易出问题。 这么写你就能看出来:
list = []
for i in 0...10
list[i]=i+1;
end
list.each do |i|
if i % 3 != 0
list.delete(i)
p "i: #{i}"
p list
p list[i]
end
end
运行的结果是:
➜ rails ruby tmp.rb
"i: 1"
[2, 3, 4, 5, 6, 7, 8, 9, 10]
3
"i: 4"
[2, 3, 5, 6, 7, 8, 9, 10]
7
"i: 7"
[2, 3, 5, 6, 8, 9, 10]
nil
"i: 10"
[2, 3, 5, 6, 8, 9]
nil
你写的代码能把人晕死~~
首先,你试图在一个可枚举对象被迭代取出的时候,删除这个可枚举对象的元素, 这种行为常常会导致不可预期的后果。
其次,改用 while 循环,而不是 if.
晕,这代码真晕。
在不创建新的数组的情况下,我怎么觉得应该用 Array#select
呢?
puts (1..100).to_a.select { |i| i % 3 == 0 }
@lgn21st 如果说在不新建数组的情况下,我们给的是不是就不对了?。。
Returns an array containing all elements of enum for which block is not false (see also Enumerable#reject).
If no block is given, an enumerator is returned instead.