arr = ["1", "2", "3b", "c3", "4", "", "5t"]
Существует два возможных подхода к этой проблеме.Один из них состоит в том, чтобы выполнить два шага: удалить все элементы, которые не являются представлениями неотрицательных целых чисел, затем преобразовать эти целые числа в числа с плавающей запятой, требуя один проход через каждый из двух массивов.Другой заключается в создании массива чисел с плавающей запятой, совершающих один проход через arr
.Это можно сделать следующим образом.
arr.each_with_object([]) { |s,a| a << s.to_f if s.match?(/\A\d+\z/) }
#=> [1.0, 2.0, 4.0]
Регулярное выражение гласит: «соответствует началу строки (якорь \A
), за которым следуют одна или несколько цифр, за которыми следует конец строки(якорь \z
). Это то же самое, что не совпадать с пустой строкой или символом, который не является цифрой, поэтому мы могли бы вместо этого написать:
arr.each_with_object([]) { |s,a| a << s.to_f unless s.empty? or s.match?(/\D/) }
#=> [1.0, 2.0, 4.0]
Выбор между этими двумя вариантами невеликздесь, но иногда последний подход легче реализовать.
Другой способ, который мне не слишком нравится (но о нем стоит знать), заключается в использовании метода Kernel # Float затем Array # compact :
arr = ["1", "-2", "3b", "c3", "4.23", "", "5t", "-1.2e3"]
arr.map { |s| Float(s) rescue nil }.compact
#=> [1.0, -2.0, 4.23, -1200.0]
Как видно, это преобразует элементы arr
, которые являются представлениями целых чисел или чисел с плавающей точкой (не только неотрицательных целых чисел), в числа с плавающей запятой (который может или не может быть необходим).
Float(s)
поднимает ArgumentError
, если s
не может быть преобразован в число с плавающей точкой. Например:
Float("3b")
#=> ArgumentError (invalid value for Float(): "3b")
Когда это происходит, япоймать исключение в строковом предложении по спасению , возвращая nil
.
Некоторым Рубиестам не нравятся встроенные спасательные предложения, потому что они могут маскировать другие ошибки.Эта проблема может быть решена только спасением ArgumentErrors
:
arr.map do |s|
begin
Float(s)
rescue ArgumentError
nil
end
end.compact
#=> [1.0, -2.0, 4.23, -1200.0]