为什么(1..5).each
会重复1,2,3,4,5
,但(5..1)
不会?它改为返回Range。
1.9.2p290 :007 > (1..5).each do |i| puts i end
1
2
3
4
5
=> 1..5
1.9.2p290 :008 > (5..1).each do |i| puts i end
=> 5..1
答案 0 :(得分:49)
最简单的方法是使用downto
5.downto(1) do |i| puts i end
答案 1 :(得分:22)
范围使用<=>
来确定迭代是否结束; 5 <=> 1 == 1
(大于),所以它在开始之前完成。即使他们没有,范围也会使用succ
进行迭代; 5.succ
是6
,但仍然运气不好。范围step
不能为负数,因此也无效。
它返回范围,因为each
返回它所调用的内容。如果它是您正在寻找的功能,请使用downto
,否则上述内容将回答您关于“为什么”的实际问题。
答案 2 :(得分:4)
您可以轻松扩展Range类,尤其是每个方法,以使其与升序和降序范围兼容:
class Range
def each
if self.first < self.last
self.to_s=~(/\.\.\./) ? last = self.last-1 : last = self.last
self.first.upto(last) { |i| yield i}
else
self.to_s=~(/\.\.\./) ? last = self.last+1 : last = self.last
self.first.downto(last) { |i| yield i }
end
end
end
然后,以下代码将按照您的预期执行:
(0..10).each { |i| puts i}
(0...10).each { |i| puts i}
(10..0).each { |i| puts i}
(10...0).each { |i| puts i}
答案 3 :(得分:1)
这甚至与Ruby没有任何关系,它只是简单的基本数学:以5
开头并以1
结尾的范围为空。没有什么可以迭代的。
答案 4 :(得分:0)
因为Ruby只执行它所说的内容,而不是你mean。
它无法分辨你是否想要反向(即5,4,3,2,1),或者你是否真的只想从5开始的数字小于或等于1.理论上可能有人可能想要后者,并且因为Ruby无法分辨出你真正想要的东西,所以它会与后者一致。