2017-11-07 9 views
-1

Rubyには、繰り返し実行してその結果を直接返す素晴らしい方法があります。これには主に配列メソッドが含まれます。たとえば:whileループを使用してRuby配列を作成する最もクリーンな方法は何ですか?

def ten_times_tables 
    (1..5).map { |i| i * 10 } 
end 

ten_times_tables # => [10, 20, 30, 40, 50] 

はしかし、私は時々whileを使用して反復処理し、直接結果の配列を返すようにしたいです。例えば、アレイの内容は、期待される最終値または一部のアキュムレータ、または当社の制御外の条件であってもよい。

A(不自然)の例のようになります。私には

def fibonacci_up_to(max_number) 
    sequence = [1, 1] 

    while sequence.last < max_number 
    sequence << sequence[-2..-1].reduce(:+) 
    end 

    sequence 
end 

fibonacci_up_to(5) # => [1, 1, 2, 3, 5] 

、この種のアプローチは非常に「非ルビー」を感じています。私が構築し、名前を付け、後で配列を返すという事実は、アンチパターンのように感じます。これまでのところ、私が思い付くことができる最高はtapを使用しているが、それはまだ非常に不快な(そして非常ネストされた)感じている:

def fibonacci_up_to(max_number) 
    [1, 1].tap do |sequence| 
    while sequence.last < max_number 
     sequence << sequence[-2..-1].reduce(:+) 
    end 
    end 
end 

誰がこの種の問題への賢い解決策を持っていますか? (多分あなたの不自然な例は、あなたの実際の使用の場合よりも、この多くの方にフィットしますが)あなたはこのような状況のために見たいと思うかもしれません

+0

あなたの人為的なシナリオは、あなたの言うとおり、非常に珍しいです。したがって、結果を達成するためのコードは少し珍しいように見えます。しかし、私はあなたの元のアプローチやそれを改善するための重要な方法について特に間違ったものは見当たりません。 –

答えて

5

何かがEnumeratorを作成しているので、あなたの不自然な例は次のようになります。ドキュメントから

初期化のために:その後、

fib = Enumerator.new do |y| 
    a = b = 1 
    loop do 
    y << a 
    a, b = b, a + b 
    end 
end 

とそれを呼び出す:

p fib.take_while { |elem| elem <= 5 } 
#=> [1, 1, 2, 3, 5] 

だから、あなたはあなたがそれを反復処理とに

0

同様に通常のRubyっぽいのいずれかの方法で使用するアレイのための必要な値を収集することができることをしたら、その後、すべての値を反復処理し、列挙子を作成しますシンプルなライムの列挙子ソリューションは、あなたは列挙子で自分自身をラップする方法を記述することができます。

def fibonacci_up_to(max_number) 
    return enum_for(__callee__, max_number) unless block_given? 

    a = b = 1 
    while a <= max_number 
    yield a 
    a, b = b, a + b 
    end 
end 

fibonacci_up_to(5).to_a # => [1, 1, 2, 3, 5] 

これは、メソッドから列挙子のインスタンスを返すように同じ結果を達成し、それは少し立派に見えるとあなたはyieldを使用することができますブロック変数yielderの代わりにキーワードを使用します。

関連する問題