Есть ли в ruby способ превратить fixnum, например 74239
, в массив, например [7,4,2,3,9]
?
Преобразование длинного фиксированного числа в массив Ruby
Ответы (7)
Вам не нужно совершать кругосветное путешествие по стране струн для такого рода вещей:
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]
.map(&:to_i)
чтобы сделать его более элегантным?
- person oldergod; 16.10.2012
-23.to_s.split('').map(&:to_i)
?
- person mu is too short; 16.10.2012
74239.to_s.chars
кажется более подходящим, чем 74239.to_s.split('')
, особенно в сочетании с .map(&:to_i)
:)
- person Adam Eberlin; 29.10.2012
each_char
было бы даже более подходящим, так как это позволило бы избежать промежуточного звена Array
, созданного chars
.
- person Drenmi; 26.04.2015
.chars
сейчас в Enumerator, а не в Array.
- person Nakilon; 19.06.2017
Метод 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]
Это немного более элегантно, чем расщепление.
Начиная с 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#method-i-digits
Вы также можете использовать 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
digits
, представленного в Ruby 2.4, делает все остальные устаревшими. - person steenslag   schedule 19.11.2020