If I have the integer 123 and I want to break the digits into an array [1,2,3] what is the best way of doing this? I have messed around with this a lot and I have the follo
It is easier to work on the UTF-8 representation of the number string because the UTF-8 code unit of a decimal digit can easily be converted to the corresponding integer by subtracting a constant:
let asciiZero = UInt8(ascii: "0")
let digits = map(String(number).utf8) { Int($0 - asciiZero) }
This also turned out to be significantly faster.
If performance is the primary goal then you should restrict the method to simple integer arithmetic, without using strings or characters:
var digits : [Int] = []
while number > 0 {
digits.insert(number % 10, atIndex: 0)
number /= 10
}
Here is my complete test code for your convenience (compiled with Xcode 6.4 in Release mode on a MacBook Pro).
func digits1(number : Int) -> [Int] {
let digits = Array(String(number)).map{Int(strtoul((String($0)), nil, 16))}
return digits
}
func digits2(number : Int) -> [Int] {
// Use a static property so that the constant is initialized only once.
struct Statics {
static let asciiZero = UInt8(ascii: "0")
}
let digits = map(String(number).utf8) { Int($0 - Statics.asciiZero) }
return digits
}
func digits3(var number : Int) -> [Int] {
var digits : [Int] = []
while number > 0 {
digits.insert(number % 10, atIndex: 0)
number /= 10
}
return digits
}
func measure(converter: (Int)-> [Int]) {
let start = NSDate()
for n in 1 ... 1_000_000 {
let digits = converter(n)
}
let end = NSDate()
println(end.timeIntervalSinceDate(start))
}
measure(digits1) // 10.5 s
measure(digits2) // 1.5 s
measure(digits3) // 0.9 s
Update for Swift 3:
func digits(_ number: Int) -> [Int] {
var number = number
var digits: [Int] = []
while number > 0 {
digits.insert(number % 10, at: 0)
number /= 10
}
return digits
}
print(digits(12345678)) // [1, 2, 3, 4, 5, 6, 7, 8]
This also turned out to be slightly faster than appending the digits to an array and reversing it at the end.