Is there a method in ruby to turn fixnum like 74239
into an array like [7,4,2,3,9]
?
You don't need to take a round trip through string-land for this sort of thing:
def digits(n)
Math.log10(n).floor.downto(0).map { |i| (n / 10**i) % 10 }
end
ary = digits(74239)
# [7, 4, 2, 3, 9]
This does assume that n
is positive of course, slipping an n = n.abs
into the mix can take care of that if needed. If you need to cover non-positive values, then:
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
Maybe not the most elegant solution:
74239.to_s.split('').map(&:to_i)
Output:
[7, 4, 2, 3, 9]
.map(&:to_i)
to get it a bit more elegant? –
Juniejunieta -23.to_s.split('').map(&:to_i)
? –
Halinahalite 74239.to_s.chars
seems more appropriate than 74239.to_s.split('')
, especially when used in conjunction with .map(&:to_i)
:) –
Stertor each_char
would be even more appropriate, as it would avoid the intermediate Array
created by chars
. –
Linea .chars
in Enumerator currently, not Array. –
Townie You don't need to take a round trip through string-land for this sort of thing:
def digits(n)
Math.log10(n).floor.downto(0).map { |i| (n / 10**i) % 10 }
end
ary = digits(74239)
# [7, 4, 2, 3, 9]
This does assume that n
is positive of course, slipping an n = n.abs
into the mix can take care of that if needed. If you need to cover non-positive values, then:
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
As of Ruby 2.4, integers (FixNum
is gone in 2.4+) have a built-in digits
method that extracts them into an array of their digits:
74239.digits
=> [9, 3, 2, 4, 7]
If you want to maintain the order of the digits, just chain reverse
:
74239.digits.reverse
=> [7, 4, 2, 3, 9]
Docs: https://ruby-doc.org/core-2.4.0/Integer.html#method-i-digits
The divmod method can be used to extract the digits one at a time
def digits n
n= n.abs
[].tap do |result|
while n > 0
n,digit = n.divmod 10
result.unshift digit
end
end
end
A quick benchmark showed this to be faster than using log to find the number of digits ahead of time, which was itself faster than string based methods.
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)
You can convert to string and use the chars method:
74239.to_s.chars.map(&:to_i)
Output:
[7, 4, 2, 3, 9]
Its a bit more elegant than splitting.
You can also use Array.new
instead of 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
In Ruby 2.4, integers will have a digits method.
© 2022 - 2024 — McMap. All rights reserved.
digits
method introduced in Ruby 2.4 makes all others obsolete. – Telemechanics