web-dev-qa-db-ja.com

Rubyの範囲の違いと時間の違いのループ

Rubyを使用してプロジェクトオイラーの問題を解決しようとしています。for-loop、times、range、uptoメソッドの4つの異なるループメソッドを使用しましたが、timesメソッドは期待される回答しか生成しませんが、for-loop、range、 uptoメソッドにはありません。私はそれらが幾分同じであると仮定していますが、私はそれが違うことを発見しました。誰かがこれらの方法の違いを説明できますか?

これが私が使ったループ構造です

# for-loop method
for n in 0..1
  puts n
end

0
1
=> 0..1

# times method
2.times do |n|
  puts n
end

0
1
=> 2

# range method
(0..1).each do |n|
  puts n
end

0
1
=> 0..1

# upto method
0.upto(1) do |n|
  puts n
end

0
1
=> 0
27
jbjuly

この情報は、ドキュメントを調べることで簡単に取得できます。

_Array#each_ の署名は_array.each {|item| block } → array_であるため、_foo.each { ... }_の戻り値はfooであることがわかります。

同様に、 _Int#upto_ にはint.upto(limit) {|i| block } => intのシグネチャがあるため、x.upto(y) { ... }は常にxを返します。

次に、 _2.times { ... }_ の署名があるため、_Integer#times_が2を返すこともわかります。

適切なドキュメントが見つからないのですが、_for x in y..._が_y.each do |x| ..._に変換されるため、for-inループが_.each_ループと同じものを返します。

とにかく、これらのループ構造のreturn値に応じて...奇妙なアプローチです。私はこれが慣用的なRubyコードで多く発生するのではないかと思います)。

8
Mark Rushakoff

私があなたを正しく理解しているのなら、_n.times_がnを含まずに反復する唯一の方法である理由を尋ねているでしょう。その場合:

範囲の場合は簡単です。_x..y_はxからyまでの範囲を定義し、_x...y_はxからyまでの範囲を定義します。したがって、時間と同じ動作が必要な場合は、_0...n_を使用します。

x.upto(y)の場合、yを含めてそれまで反復するバージョンは1つだけです。これは単に、動作するように定義され、文書化されている方法です。

_n.times_にnが含まれない理由も明確です。0からn(両端を含む)まで反復した場合、_n+1_時間が生成されます。ただし、このメソッドは_n.times_と呼ばれるため、明らかにn回しか生成されません。

3
sepp2k