如何在一行中写条件语句?轨道

时间:2011-01-07 17:30:41

标签: ruby-on-rails ruby refactoring

我想说这个

self.preferred_amount * object.each{|li|li.variant}.collect{|li|li.weight}

唯一的问题是某些权重等于零。

在这种情况下,我想补充一点,如果它们相等,则将它们设为0。

有没有办法将这个逻辑合并到同一行?

或者有没有办法让这句话比它更重构?

5 个答案:

答案 0 :(得分:8)

li.weight更改为li.weight || 0

||是“短路或”运营商。如果它的左侧是真的(既不是假也不是零),它会返回左侧,否则它会返回右侧。

MRI> = 1.8.7中有一项功能可以让你做到这一点。而不是:

each{|li|li.variant}

你可以写

each(&:variant)

在1.8.7之前的Ruby版本中,需要backports gem才能获得此功能。

更好的是,将所有逻辑移到对象的类中,例如

class Whatever
  def variant_weights
    each(&:variant).collect{ |li| li.weight || 0}
  end
end

并使用它:

self.preferred_amount * object.variant_weights

但请注意,将标量乘以数组是一个错误。如果你的意思是加权,那么:

class Whatever
  def total_variant_weights
    each(&:variant).collect{ |li| li.weight || 0}.inject(&:+)
  end
end

并使用它:

self.preferred_amount * object.total_variant_weights

答案 1 :(得分:5)

请注意,上述所有答案都是正确,但是要直接回答您的问题:

  

如何在一行中编写条件语句?轨道

您可以使用三元运算符。他们采取以下形式:

assertion ? value_if_true : value_if_false
# if assertion is true, then value_if_true, otherwise, value_if_false

例如:

puts 4 < 5 ? 'you are on Earth' : 'you are on another planet'
<%= @user.is_admin? ? 'you can access this page' : 'you aren\'t allowed to be here' %>

就像我说的,上面的答案实际上就是你想要的特定操作(不是三元运算符在这种情况下不会工作)。我只是想让你更深入地了解一线人。

另请注意,这不是特定于Ruby的。大多数编程语言(包括Ruby,PHP,CF,AS,JAVA,C,C#......)都有三元运算符。

答案 2 :(得分:2)

|| 0重量:

self.preferred_amount * object.each{|li|li.variant}.collect{|li|li.weight || 0}

答案 3 :(得分:2)

尝试

 .collect{|li|li.weight || 0}

答案 4 :(得分:2)

每个似乎都是多余的。怎么样:

self.preferred_amount * object.collect { |o| o.variant.weight.to_i }

或者如果你真的想要加权:

self.preferred_amount * object.inject { |sum, o| sum + o.variant.weight.to_i }