如何迭代整数的各个数字?

23

可能是重复问题:
将长的固定数字转换为数组 Ruby

目前,我需要在 Ruby 中迭代整数的各个数字。现在,我只是将它分成一个数组,然后对其进行迭代。但是我想知道是否有更快的方法可以做到这一点?


你所说的更快是什么意思?更高效还是更简洁? - Alex Peattie
2
顺便问一下,它是字符串还是Fixnum类型的整数?(1233或“1233”) - Roberto Decurnex
请展示一下你现在是如何做的,这样我们就有一个参考。 - tokland
@robertodecurnex,这是一个Fixnum,它被转换为一个字符串数组,然后再转换为整数。 - Rivasa
1
这是一个非常有趣的问题。 "正常"的方法(如已经在一个答案中提到的)是 number.to_s.each_char(&:to_i)number.to_s.chars.map(&:to_i)。但是,如果你想要一些速度...本主题中的回答也很好! - musicmatze
6个回答

47

最短的解决方案可能是:

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]

只需迭代数字,也可以使用数组切片方法,是吗?n = 12.to_ssum = (n[0..1].to_i + n[1..2].to_i)product = (n[0,1].to_i * n[1,1].to_i) - Linju

15

你可以使用取模/除以10的旧技巧,但是除非你有非常大的数字,否则这并不会明显更快,并且它会反向给出数字:

i = 12345

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

输出:

5
4
3
2
1

5
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]

5
Ruby有一个名为divmod的方法,可以一次计算出x%10x/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这样速度很重要的问题,这是非常有用的。在整数上定义它可以使它在大整数上可用。


5

我喜欢使用枚举类型来实现这个目的:

class Integer
  def digits
    to_s.each_char.lazy.map(&:to_i)
  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]

# ...

也许 to_s.chars.each { |c| x << c.to_i } 更符合正统,因为该块执行了副作用? - tokland
1
@tokland 谢谢你的好建议,我编辑了我的答案,使用了一个懒惰枚举器来消除可能的副作用。 - Patrick Oscity

2
尝试对10取模(将会给你最后一位数字),然后除以10(将会给你剩下的数字),重复这个步骤直到你只剩下最后一个数字。当然,如果你想从左到右依次查看数字,你需要颠倒它们的顺序。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接