0

I was wondering if there was a way in Swift to split an Int up into it's individual digits without converting it to a String. For example:

let x: Int = 12345
//Some way to loop/iterate over x's digits
//Then map each digit in x to it's String value
//Return "12345"

For a bit of background, I'm attempting to create my own method of converting an Int to a String without using the String description property or using String Interpolation.

I've found various articles on this site but all the ones I've been able to find either start with a String or end up using the String description property to convert the Int to a String.

Thanks.

Hamish
  • 78,605
  • 19
  • 187
  • 280
swifty-D
  • 11
  • 1
  • 3

3 Answers3

3

Just keep dividing by 10 and take the remainder:

extension Int {
    func digits() -> [Int] {
        var digits: [Int] = []
        var num = self
        repeat {
            digits.append(num % 10)
            num /= 10
        } while num != 0
        return digits.reversed()
    }
}

x.digits() // [1,2,3,4,5]

Note that this will return all negative digits if the value is negative. You could add a special case if you want to handle that differently. This return [0] for 0, which is probably what you want.

And because everyone like pure functional programming, you can do it that way too:

func digits() -> [Int] {
    let partials = sequence(first: self) {
        let p = $0 / 10
        guard p != 0 else { return nil }
        return p
    }

    return partials.reversed().map { $0 % 10 }
}

(But I'd probably just use the loop here. I find sequence too tricky to reason about in most cases.)

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • You should probably solve the negative numbers too as the other answer is doing. With your solution negative numbers have negative digits. – Sulthan Feb 28 '17 at 13:50
  • just append `abs(num % 10)` instead of `num % 10`, because `-9992` is not formed from `-9`,`-9`,`-9` and `-2`, it is formed from `9`(3 times) and `2` – Mr. Xcoder Feb 28 '17 at 13:52
  • It would be way better if `digits` function would accept `radix` parameter (with 10, maybe, being default value). – user28434'mstep Feb 28 '17 at 14:19
1

A recursive way...

extension Int {
    func createDigitArray() -> [Int] {
        if self < 10 {
            return [self]
        } else {
            return (self / 10).createDigitArray() + [self % 10]
        }
    }
}
12345.createDigitArray() //->[1, 2, 3, 4, 5]
OOPer
  • 47,149
  • 6
  • 107
  • 142
  • not working for negative numbers, since it returns the whole number instead of its digits... – Mr. Xcoder Feb 28 '17 at 14:46
  • you should change the condition to `if self < 10 && self >= 0` and handle the `-` in front of digits for the cases which are < 0 – Mr. Xcoder Feb 28 '17 at 14:50
1

A very easy approach would be using this function:

func getDigits(of number: Int) -> [Int] {
    var digits = [Int]()
    var x = number
    repeat{
        digits.insert(abs(x % 10), at: 0)
        x/=10
    } while x != 0

    return digits
}

And using it like this:

getDigits(of: 97531) // [9,7,5,3,1]
getDigits(of: -97531) // [9,7,5,3,1]

As you can see, for a negative number you will receive the array of its digits, but at their absolute value (e.g.: -9 => 9 and -99982 => 99982)

Hope it helps!

Mr. Xcoder
  • 4,719
  • 5
  • 26
  • 44