Ruby中的DRY - 可以重复一行代码吗?

时间:2016-05-23 16:07:03

标签: ruby dry

我是编程和红宝石的新手。我正在使用一种方法来识别某人的秘密圣诞老人是谁。该方法采用String和Integer参数(名字或id)。我有String和Integer参数的不同代码。这导致为不同的参数重复相同的代码行(secret = PERSONS [person [:santa] -1])。

我的问题有两个方面:

  1. 这种重复是否符合DRY原则?还有另一种方法可以避免重复吗?

  2. 看到我在迭代器之外初始化了local_variable秘密,并使用迭代器传递给该变量。这是最有效的方法吗?我可以在不初始化局部变量的情况下从迭代器返回一个值吗?

  3. 我的代码如下。另外,我正在附上我正在运行代码的数据样本散列(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=>"<luke@theforce.net>",
      :santa=>4},
     {:id=>2,
      :first_name=>"Leia",
      :last_name=>"Skywalker",
      :email=>"<leia@therebellion.org>",
      :santa=>7},
     {:id=>3,
      :first_name=>"Toula",
      :last_name=>"Portokalos",
      :email=>"<toula@manhunter.org>",
      :santa=>5},
     {:id=>4,
      :first_name=>"Gus",
      :last_name=>"Portokalos",
      :email=>"<gus@weareallfruit.net>",
      :santa=>2},
     {:id=>5,
      :first_name=>"Bruce",
      :last_name=>"Wayne",
      :email=>"<bruce@imbatman.com>",
      :santa=>3},
     {:id=>6,
      :first_name=>"Virgil",
      :last_name=>"Brigman",
      :email=>"<virgil@rigworkersunion.org>",
      :santa=>1},
     {:id=>7,
      :first_name=>"Lindsey",
      :last_name=>"Brigman",
      :email=>"<lindsey@iseealiens.net>",
      :santa=>6}]
    

1 个答案:

答案 0 :(得分:1)

在这种情况下,有一种方法可以避免重复,首先检查一个错误的参数&#34;然后从阵列中选择正确的人。

对于第二个问题,您可能正在寻找select迭代器而不是每个迭代器。它将返回数组中的所有元素,使得块中的条件传递给它为真。

下面是一些代码。 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