Digits of a number in a straight order

Hi, I am wondering, is there any way of iterating over digits of a number in a straight order?
I mean significant figures of course.

The example will be:
123 -> iterate over [1, 2, 3]

I am trying to find a solution without using conversion to a String, basically without any memory allocation..
The only way I can think of is to first reverse a number and then go through the digits of the reversed number, would love to hear more ideas.

fn digits(mut x: u32) -> impl Iterator<Item=u32> {
    std::iter::from_fn(move || {
        if x > 0 {
            let digit = x%10;
            x /= 10;
            Some(digit)
        } else {
            None
        }
    })
}

Should work (except for 0)

2 Likes

To make it work with 0:

fn digits(mut x: u32) -> impl Iterator<Item = u32> {
    let iter = std::iter::from_fn(move || {
        if x > 0 {
            let digit = x % 10;
            x /= 10;
            Some(digit)
        } else {
            None
        }
    });
    (x == 0).then_some(0).into_iter().chain(iter)
}

And generically:

fn digits<T>(mut x: T) -> impl Iterator<Item = T>
where
    T: From<u8> + Copy + PartialOrd + DivAssign + Rem<Output = T>
{
    let zero = T::from(0);
    let ten = T::from(10);
    
    let iter = std::iter::from_fn(move || {
        if x > zero {
            let digit = x % ten;
            x /= ten;
            Some(digit)
        } else {
            None
        }
    });
    
    (x == zero).then_some(zero).into_iter().chain(iter)
}
2 Likes

Hi, thank you for your reply, i made a bit of mistake in the question, I meant to return digits in a straight order,
123 - 1 2 3

Thank you a lot, but I made a mistake in the question description, my bad :grinning: I meant, to iterate over digits in a straight order

Then you'd have to start dividing by the largest possible denominator (that makes sense) first, and go down from there.

1 Like

Yeah, any idea on possible optimization via getting leading_zeros()?

fn digits(mut x: u32) -> impl Iterator<Item=u32> {
    let mut place = 1_000_000_000u32;
        if place > 0 {
            let digit = (x/place)%10;
            place /= 10;
            Some(digit)
        } else {
            None
        }
    })
}

This will also generat all leading zeros but you can skip those

1 Like

Thank you!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.