2017-01-17 4 views
2

Я использую Ruby 2.4. У меня есть массив строк, которые должны быть целыми ...Как найти минимальный элемент в массиве строк, но только с учетом целых чисел?

["1", "55", "25", ... ] 

У меня есть следующий за выяснить, минимальное число в массиве

data.map(&:to_i).min 

Это прекрасно работает, за исключением того времени когда нецелая строка закрадывается в массив, как

["1", "a", "2", "3"] 

С моей data.map(&:to_i).min линии, выше возвращает ноль. Как мне изменить свой код, чтобы он принимал только min элементов в массиве, которые фактически являются целыми числами?

ответ

4

У вас есть несколько способов сделать это, но проще всего отсеивать нечисловые значения, если вы хотите игнорировать мусор:

data = ["1", "a", "2", "3"] 
data.grep(/\A\-?\d+\z/).map(&:to_i).min 
# => 1 

Метод grep делает его довольно легко выбрать вещи которые соответствуют определенной схеме, а также многим другим.

+0

@steenslag Неясно, будут ли эти данные позитивными или нет, но в любом случае я добавил необязательный '-'. – tadman

3

Когда я хочу, чтобы преобразовать строку в целое число, если и только это строковое представление целого числа, я всегда использую Kernel::Integer:

arr = ["3", "a", "2", "0x01", "0c", "0b11", "0o03", "4", "1_000"] 

arr.select { |s| Integer(s) rescue nil }.min_by { |s| Integer(s) } 
    #=> "0x01" 

Здесь

arr.select { |s| Integer(s) rescue nil } 
    #=> ["3", "2", "0x01", "0b11", "0o03", "4", "1_000"] 

Примечание "0x01".to_i #=> 0 (не!), поэтому Integer необходимо использовать дважды.

Если строка не является представлением целого числа, Integer вызывает исключение:

Integer("a") 
    #=> ArgumentError: invalid value for Integer(): "a" 

который спасен в линии, в результате чего nil должен быть возвращен, в результате чего является строка не выбрана. (Можно было бы, конечно, пойти на лишнюю милю и использовать предложение, которое снимает только ArguementError исключений.)

Вопрос запрашивает возвращаемый элемент массива (строки). Если его число эквивалентно желателен, вы можете написать:

a = arr.map { |s| Integer(s) rescue nil }.compact.min 
    #=> 1 

где

arr.map { |s| Integer(s) rescue nil } 
    #=> [3, nil, 2, 1, nil, 3, 3, 4, 1_000] 

Примечание

['a', 'b'].map { |s| Integer(s) rescue nil }.compact.min 
    #=> nil 
0

Использование Enumerable#grep_v мы можем сделать следующее и исключить многословные-строки:

arr = ["1", "a", "2", "3"] 
arr.grep_v(/[a-zA-Z]+/).min_by(&:to_i) #=> "1" 

Измените регулярное выражение так, как вам кажется.

Смежные вопросы