1
a = [4, 3, 2, nil]
a.max_by { |v| v * 2 } => NoMethodError: undefined method `*' for nil:NilClass

如何重载 max_by 以忽略 nil 值?

4

3 回答 3

10

您可以Array.compact在调用max_by.

a.compact.max_by { |v| v * 2 }
于 2012-06-25T04:54:31.700 回答
4

欢迎使用 Ruby:解决问题的方法有很多!

一个非常简单的解决方案是:

a.max_by { |v| v.to_f * 2 }

因为 nil 强制浮动为 0。这不处理负值,但由于 nil 只是一个名为 NilClass 的类的单个实例,现在与 Ruby 中的所有类一样,我们可以打开它并让它学习一点数学:

class NilClass
  # overloading * operator
  def *(y)
    # returning negative infinity: Ruby 1.8.7
    -1.0/0.0
    # returning negative infinity: Ruby 1.9.2
    # -Float::INFINITY
  end
end

现在我们有了

a.max_by { |v| v * 2 }

返回 4。

于 2012-06-25T07:54:34.847 回答
2

这是另一个:

a.max_by { |v| v.nil? ? -Float::INFINITY : v }
#=> 4

对于您的示例,这显然比 更复杂compact,但是如果您想对数组进行排序并保留nil值,这是一个方便的技巧。或者,如果您想以一种奇怪的方式进行排序,比如最后的零:

[0,4,5,6,1,9].sort_by { |v| v.zero? ? Float::INFINITY : v }
#=> [1, 4, 5, 6, 9, 0]
于 2012-06-25T07:21:21.573 回答