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

DRY in Ruby - Is it okay to repeat a line of code?

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

我的问题有两个:

  1. 这种重复是否违反DRY原则?还有其他方法可以避免重复吗?

  2. 看到我在迭代器外初始化了 local_variable secret 并使用迭代器传递给那个变量。这是最有效的方法吗?我可以只 return 来自迭代器的值而不初始化局部变量吗?

我的代码如下。另外,我附上了我 运行 代码的数据散列样本(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}]

在这种情况下,有一种方法可以避免重复,方法是首先检查 "bad argument",然后从数组中选择正确的人。

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

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