为什么下降时范围不起作用?

时间:2012-01-11 16:21:04

标签: ruby range

为什么(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

5 个答案:

答案 0 :(得分:49)

最简单的方法是使用downto

5.downto(1) do |i| puts i end

答案 1 :(得分:22)

范围使用<=>来确定迭代是否结束; 5 <=> 1 == 1(大于),所以它在开始之前完成。即使他们没有,范围也会使用succ进行迭代; 5.succ6,但仍然运气不好。范围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无法分辨出你真正想要的东西,所以它会与后者一致。