2012-10-26 10 views
15

Mögliche Duplizieren:
Turning long fixed number to array RubyWie durchläufe ich die Ziffern einer ganzen Zahl?

Nun, ich habe über die Ziffern einer ganzen Zahl in Ruby iterieren. Im Moment habe ich es nur in ein Array aufgeteilt und dann darüber iteriert. Ich habe mich allerdings gefragt, ob es einen schnelleren Weg dafür gibt?

+0

Was meinst du schneller? Leistungsfähiger oder prägnanter? –

+2

@link Btw, ist es eine ganze Zahl als String oder Fixnum? (1233 oder "1233") – robertodecurnex

+0

Bitte zeigen Sie, wie Sie es jetzt tun, damit wir eine Referenz haben. – tokland

Antwort

32

Die kürzeste Lösung wahrscheinlich ist:

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

Ein orthodoxer mathematischer Ansatz:

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] 
+0

Um nur die Ziffern zu durchlaufen, können Sie auch Array-Slice-Methoden verwenden, richtig? n = 12.to_s sum = (n [0..1] .to_i + n [1..2] .to_i) product = (n [0,1] .to_i * n [1, 1] .to_i) – Linju

2

Versuchen Sie Mod um 10 (geben Sie die letzte Ziffer), dann dividieren durch 10 (geben Sie den Rest der Ziffern), wiederholen Sie dies, bis Sie auf die letzte Ziffer sind. Natürlich müssen Sie die Reihenfolge umkehren, wenn Sie die Ziffern von links nach rechts durchgehen wollen.

14

Sie können von 10 den alten Trick des Moduls/Divisions verwenden, aber dies wird nicht messbar schneller sein, wenn Sie riesige Zahlen haben, und es werden die Ziffern Sie zurück geben:

i = 12345 

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

Ausgang:

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

Ruby hat divmod, die sowohl x%10 und x/10 in einem Rutsch berechnen werden:

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] 

Für Dinge wie Project Euler, wo Geschwindigkeit von etwas wichtig, das ist schön zu haben. Wenn Sie es auf Integer definieren, ist es auch auf Bignum verfügbar.

2

Ich mag Enumerator Güte. Ich schrieb diesen Code für ein Projekt von mir:

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

Dies ermöglicht Ihnen den Zugriff auf alle guten Enumerator Zeug:

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 
Verwandte Themen