Break A Number Up To An Array of Individual Digits

后端 未结 5 1862
陌清茗
陌清茗 2020-12-02 00:32

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

5条回答
  •  有刺的猬
    2020-12-02 01:06

    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.

提交回复
热议问题