What is a stable way to iterate on a range with custom step?

前端 未结 6 906
不思量自难忘°
不思量自难忘° 2021-01-01 18:41

How should I go if I want to iterate with a custom step in stable Rust? Essentially something like the C/C++

for (in         


        
6条回答
  •  执念已碎
    2021-01-01 19:25

    Rust 1.28+

    Iterator::step_by is now stable:

    fn main() {
        for i in (0..100).step_by(2) {
            println!("{}", i);
        }
    }
    

    Rust 1.1+

    You can always write it out the old-fashioned way:

    fn main() {
        let mut i = 0;
        while i < 100 {
            println!("i: {}", i);
            i += 2;
        }
    }
    

    Which can then be abstracted:

    use std::ops::Add;
    
    fn step_by(start: T, end_exclusive: T, step: T, mut body: F)
    where
        T: Add + PartialOrd + Copy,
        F: FnMut(T),
    {
        let mut i = start;
        while i < end_exclusive {
            body(i);
            i = i + step;
        }
    }
    
    fn main() {
        step_by(0, 100, 2, |i| {
            println!("i: {}", i);
        })
    }
    

    Interesting historical side note, I believe that originally all the looping was done with closures like this, before iterators became extremely prevalent.

    You can then take this and make it into an iterator:

    use std::ops::Add;
    
    struct StepBy {
        start: T,
        end_exclusive: T,
        step: T,
    }
    
    impl StepBy {
        fn new(start: T, end_exclusive: T, step: T) -> Self {
            Self {
                start,
                end_exclusive,
                step,
            }
        }
    }
    
    impl Iterator for StepBy
    where
        T: Add + PartialOrd + Copy,
    {
        type Item = T;
        fn next(&mut self) -> Option {
            if self.start < self.end_exclusive {
                let v = self.start;
                self.start = self.start + self.step;
                Some(v)
            } else {
                None
            }
        }
    }
    
    fn main() {
        for i in StepBy::new(0, 100, 2) {
            println!("i: {}", i);
        }
    }
    

    See also:

    • How can I add new methods to Iterator?

提交回复
热议问题