Breedly
Breedly

Reputation: 14226

How do I write a value doubling iterator?

I want to start with a base value of 1 and then multiply my base value by 2 each iteration up to a defined limit (say the total length of my array).

Do I have to implement a special iterator just to do this? Or can I combine other iterator methods like map and filter together in order to achieve the same functionality. Though I would imagine implementing my iterator specifically would be more efficient, but also more verbose.

Upvotes: 0

Views: 343

Answers (2)

Shepmaster
Shepmaster

Reputation: 430320

You can use Iterator::scan:

use std::iter;

fn main() {
    let items = iter::repeat(()).scan(1i32, |state, _| {
        let current_state = *state;
        *state = current_state * 2;
        Some(current_state)
    });

    println!("{:?}", items.take(10).collect::<Vec<_>>());
}

This has a small state which starts with your initial value (1i32) and doubles the state each time, returning the previous one.


Since closures capture their environment, you can do this without scan, although I like my iterators to contain all the info they need, so I'd be unlikely to actually do this:

let mut state = 1;
let items = iter::repeat(()).map(|_| {
    let v = state;
    state *= 2;
    v
});

And there's always the long-form:

struct Doubling {
    value: i32,
}

impl Doubling {
    fn new(value: i32) -> Self {
        Self { value }
    }
}

impl Iterator for Doubling {
    type Item = i32;

    fn next(&mut self) -> Option<Self::Item> {
        let val = self.value;
        self.value *= 2;
        Some(val)
    }
}

fn main() {
    let items = Doubling::new(1);
    println!("{:?}", items.take(10).collect::<Vec<_>>());
}

Upvotes: 5

ljedrz
ljedrz

Reputation: 22163

You could do the following:

fn main() {
    for i in (0..).map(|n| 2usize.pow(n)).take(10) { // take(10) so it stops
        println!("{}", i);
    }
}

Output:

1
2
4
8
16
32
64
128
256
512

It's pretty efficient, there's no need to implement your own iterator for this.

Upvotes: 5

Related Questions