Превращение длинного фиксированного числа в массив Ruby

Есть ли способ в ruby, чтобы включить fixnum, как 74239 в массив, как [7,4,2,3,9]?

6 ответов

Решение

Вам не нужно совершать путешествие туда-обратно по суше для такого рода вещей:

def digits(n)
    Math.log10(n).floor.downto(0).map { |i| (n / 10**i) % 10 }
end

ary = digits(74239)
# [7, 4, 2, 3, 9]

Это предполагает, что n положительно, конечно, поскользнуться n = n.abs в смеси могут позаботиться об этом, если это необходимо. Если вам нужно охватить неположительные значения, то:

def digits(n)
    return [0] if(n == 0)
    if(n < 0)
       neg = true
       n   = n.abs
    end
    a = Math.log10(n).floor.downto(0).map { |i| (n / 10**i) % 10 }
    a[0] *= -1 if(neg)
    a
end

Возможно, не самое элегантное решение:

74239.to_s.split('').map(&:to_i)

Выход:

[7, 4, 2, 3, 9]

Начиная с Ruby 2.4, целые числа ( FixNumотсутствует в 2.4+) есть встроенныйdigits метод, который извлекает их в массив их цифр:

74239.digits
=> [9, 3, 2, 4, 7]

Если вы хотите сохранить порядок цифр, просто объедините reverse:

74239.digits.reverse
=> [7, 4, 2, 3, 9]

Документы: https://ruby-doc.org/core-2.4.0/Integer.html

Метод divmod может использоваться для извлечения цифр по одной за раз

def digits n
  n= n.abs
  [].tap do |result|
    while n > 0 
      n,digit = n.divmod 10
      result.unshift digit
    end
  end
end

Быстрый тест показал, что это быстрее, чем использование журнала для определения количества цифр раньше времени, что само по себе быстрее, чем строковые методы.

bmbm(5) do |x|
  x.report('string') {10000.times {digits_s(rand(1000000000))}}
  x.report('divmod') {10000.times {digits_divmod(rand(1000000000))}}
  x.report('log') {10000.times {digits(rand(1000000000))}}
end

#=>
             user     system      total        real
string   0.120000   0.000000   0.120000 (  0.126119)
divmod   0.030000   0.000000   0.030000 (  0.023148)
log      0.040000   0.000000   0.040000 (  0.045285)

Вы можете преобразовать в строку и использовать метод chars:

74239.to_s.chars.map(&:to_i)

Выход:

[7, 4, 2, 3, 9]

Это немного элегантнее, чем разделение.

Вы также можете использовать Array.new вместо map:

n = 74239

s = Math.log10(n).to_i + 1 # Gets the size of n

Array.new(s) { d = n % 10; n = n / 10; d }.reverse 

В Ruby 2.4 целые числа будут иметь метод цифр.

Другие вопросы по тегам