a = [4, 3, 2, nil]
a.max_by { |v| v * 2 } => NoMethodError: undefined method `*' for nil:NilClass
Как перегрузить max_by, чтобы игнорировать значения nil?Как расширить Ruby Перечислимый класс max_by игнорировать nil?
a = [4, 3, 2, nil]
a.max_by { |v| v * 2 } => NoMethodError: undefined method `*' for nil:NilClass
Как перегрузить max_by, чтобы игнорировать значения nil?Как расширить Ruby Перечислимый класс max_by игнорировать nil?
Добра пожаловать в Ruby: Есть так много способов решить эту проблему!
очень простое решение:
a.max_by { |v| v.to_f * 2 }
так нолю принуждают плавать как 0. Это не обрабатывает отрицательные значения, но так как ноль только один экземпляр класса под названием NilClass, теперь, как с все классы в Ruby, мы можем открыть ему позволить ей выучить littly математику:
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 }
return 4.
Вы можете использовать Array.compact
, чтобы удалить нильсы, прежде чем звонить по телефону max_by
.
a.compact.max_by { |v| v * 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]
Хотя он работает, он не совсем отвечает на вопрос OP (как расширить класс Enumerable). –