2016-05-23 22 views
-2

私はプログラミングとルビーの初心者です。私は、誰かの秘密のサンタが誰であるかを特定する方法を使用しています。このメソッドは、String引数とInteger引数(ファーストネームまたはID)を取ります。私は文字列と整数の引数のための異なるコードを持っています。これにより、異なる引数(secret = PERSONS [person [:santa] -1))に対して同じコード行が繰り返されます。RubyのDRY - コード行を繰り返しても問題ありませんか?

私の質問は2つある:

  1. はDRY原則に対する繰り返しのこの種のですか?繰り返しを避ける別の方法がありますか?

  2. イテレータの外側でlocal_variable secretを初期化し、イテレータを使用してその変数に渡します。これはこれを行う最も効率的な方法ですか?ローカル変数を初期化せずにイテレータから値を返すことはできますか?

マイコードは以下のとおりです。また、コードを実行しているデータ(PERSONS)のサンプルハッシュを囲んでいます。

def who_is_secret_santa(first_name) 
    secret = nil 
    PERSONS.each do |person| 
    if first_name.is_a? String 
     if person[:first_name] == first_name 
     secret = PERSONS[person[:santa]-1] 
     end 
    elsif first_name.is_a? Integer 
     if person[:id] == first_name 
     secret = PERSONS[person[:santa]-1] 
     end 
    else 
     puts "Bad argument" 
    end 
    end 
    puts "#{first_name}'s Secret Santa " + (secret ? "is #{secret[:first_name]}" : "not found") 
end 


[{:id=>1, 
    :first_name=>"Luke", 
    :last_name=>"Skywalker", 
    :email=>"<[email protected]>", 
    :santa=>4}, 
{:id=>2, 
    :first_name=>"Leia", 
    :last_name=>"Skywalker", 
    :email=>"<[email protected]>", 
    :santa=>7}, 
{:id=>3, 
    :first_name=>"Toula", 
    :last_name=>"Portokalos", 
    :email=>"<[email protected]>", 
    :santa=>5}, 
{:id=>4, 
    :first_name=>"Gus", 
    :last_name=>"Portokalos", 
    :email=>"<[email protected]>", 
    :santa=>2}, 
{:id=>5, 
    :first_name=>"Bruce", 
    :last_name=>"Wayne", 
    :email=>"<[email protected]>", 
    :santa=>3}, 
{:id=>6, 
    :first_name=>"Virgil", 
    :last_name=>"Brigman", 
    :email=>"<[email protected]>", 
    :santa=>1}, 
{:id=>7, 
    :first_name=>"Lindsey", 
    :last_name=>"Brigman", 
    :email=>"<[email protected]>", 
    :santa=>6}] 
+0

はこれを見てください:http://rubyofftherails.blogspot.com.br/2016/05/better-algorithms.html –

+0

は、それはあなたの特定のコードではないのですが、DRYの原則のお手伝いをすることがあります。 –

答えて

1

最初の「悪い引数」をチェックして、その後、アレイから正しい人物を選択することで、この場合の繰り返しを回避する方法があります。

2番目の質問では、おそらくそれぞれの代わりにselectイテレータが必要です。配列に渡されたすべての要素が返され、渡されたブロック内の条件がtrueになります。

以下はいくつかのコードです。 pはfirst_nameがメソッドに渡された人を表します。

def who_is_secret_santa(first_name) 
    if ! ((first_name.is_a? String) || (first_name.is_a? Integer)) 
    puts "Bad argument" 
    else 
    p = (PERSONS.select do |person| person[:first_name] == first_name || person[:id] == first_name end)[0] 
    puts "#{first_name}'s Secret Santa " + (p ? "is #{PERSONS[p[:santa]-1][:first_name]}" : "not found") 
    end 
end 
関連する問題