web-dev-qa-db-ja.com

下降時に範囲が機能しないのはなぜですか?

(1..5).each1,2,3,4,5を反復するのに、(5..1)が反復しないのはなぜですか?代わりに範囲を返します。

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
35
larryzhao

それを行う最も簡単な方法は、

5.downto(1) do |i| puts i end
50
Derek Organ

範囲は<=>を使用して、反復が終了したかどうかを判別します。 5 <=> 1 == 1(より大きい)なので、開始する前に実行されます。そうしなかったとしても、範囲はsuccを使用して繰り返されます。 5.succ6ですが、まだ運が悪いです。範囲のstepを負にすることはできないため、それも機能しません。

eachは呼び出されたものを返すため、範囲を返します。探している機能自体である場合はdowntoを使用します。それ以外の場合は、上記が「理由」に関する実際の質問に答えます。

22
Dave Newton

Range クラス、特にeachメソッドを簡単に拡張して、昇順と降順の両方の範囲と互換性を持たせることができます。

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}
5
zml

これはRubyとは実際には何の関係もありません。単純な基本的な計算です。つまり、5で始まり1で終わる範囲は空です。繰り返すことは何もありません。

1
Jörg W Mittag

Rubyは言われたことだけを行い、あなたがしたことはしません 平均

逆にしたいか(つまり、5、4、3、2、1)、または5から始まる1以下の数字だけが本当に必要かどうかはわかりません。理論的には誰かが後者が必要な場合があります。Rubyは本当に必要なものがわからないため、後者を使用します。

0
Andrew Grimm