Как выполнить итерацию по цифрам целого числа?

Возможный дубликат:
Превращение длинного фиксированного числа в массив Ruby

Ну, я должен перебирать цифры целого числа в Ruby. Прямо сейчас я просто разбил его на массив, а затем повторил это. Однако мне было интересно, есть ли более быстрый способ сделать это?

Ответы

Ответ 1

Самое короткое решение, вероятно, следующее:

1234.to_s.chars.map(&:to_i)
#=> [1, 2, 3, 4]

Более ортодоксальный математический подход:

class Integer
  def digits(base: 10)
    quotient, remainder = divmod(base)
    quotient == 0 ? [remainder] : [*quotient.digits(base: base), remainder]
  end
end

0.digits #=> [0]
1234.digits #=> [1, 2, 3, 4]
0x3f.digits(base: 16) #=> [3, 15]

Ответ 2

Вы можете использовать старый трюк модуля/деления на 10, но это не будет заметно быстрее, если у вас нет огромных чисел, и он будет давать цифры вам назад:

i = 12345

while i > 0 
  digit = i % 10
  i /= 10
  puts digit
end

Вывод:

5
4
3
2
1

Ответ 3

split=->(x, y=[]) {x < 10 ? y.unshift(x) : split.(x/10, y.unshift(x%10))}

split.(1000) #=> [1,0,0,0]
split.(1234) #=> [1,2,3,4]

Ответ 4

Попробуйте по mod на 10 (даст вам последнюю цифру), затем разделите на 10 (вы получите остальную часть цифр), повторите это, пока не опуститесь до последней цифры. Конечно, вам придется отменить порядок, если вы хотите пройти цифры слева направо.

Ответ 5

Ruby имеет divmod, который будет вычислять как x%10, так и x/10 за один раз:

class Integer
  def split_digits
    return [0] if zero?
    res = []
    quotient = self.abs #take care of negative integers
    until quotient.zero? do
      quotient, modulus = quotient.divmod(10) #one go!
      res.unshift(modulus) #put the new value on the first place, shifting all other values
    end
    res # done
  end
end

p 135.split_digits #=>[1, 3, 5]

Для таких вещей, как Project Euler, где скорость имеет некоторое значение, это приятно иметь. Определение его на Integer заставляет его быть доступным и на Bignum.

Ответ 6

Мне нравится доброжелательность. Я написал этот код для моего проекта:

class Integer
  def digits
    Enumerator.new do |x|
      to_s.chars.map{|c| x << c.to_i }
    end
  end
end

Это дает вам доступ ко всем хорошим материалам Enumerator:

num = 1234567890

# use each to iterate over the digits
num.digits.each do |digit|
  p digit
end

# make them into an array
p num.digits.to_a     # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]

# or take only some digits
p num.digits.take(5)  # => [1, 2, 3, 4, 5]

# you can also use next and rewind
digits = num.digits
p digits.next         # => 1
p digits.next         # => 2
p digits.next         # => 3
digits.rewind
p digits.next         # => 1