Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rust iterators and looking forward (peek/multipeek)

Tags:

iteration

rust

I am trying to use a pattern with iterators in Rust and falling down somewhere, apparently simple.

I would like to iterate through a container and find an element with a predicate [A] (simple), but then look forward using another predicate and get that value [B] and use [B] to mutate [A] in some way. In this case [A] is mutable and [B] can be immutable; this makes no difference to me, only to the borrow checker (rightly).

It would help to understand this with a simple scenario, so I have added a small snippet to let folk see the issue/attempted goal. I have played with itertools and breaking into for/while loops, although I want to remain as idiomatic as possible.

Silly Example scenario

Lookup an even number, find next number that is divisible by 3 and add to the initial number.

#[allow(unused)]
fn is_div_3(num: &u8) -> bool {
    num % 3 == 0
}

fn main() {
    let mut data: Vec<u8> = (0..100).collect();

    let count = data.iter_mut()
        .map(|x| {
            if *x % 2 == 0 {
                // loop through numbers forward to next is_div_3,
                // then x = x + that number
            }
            true
        })
        .count();

    println!("data {:?}, count was {} ", data, count);
}

playground

like image 260
dirvine Avatar asked Jun 07 '16 16:06

dirvine


1 Answers

Sadly I'm a bit late, but here goes.

It's not totally pretty, but it's not as bad as the other suggestion:

let mut data: Vec<u8> = (1..100).collect();

{
    let mut mut_items = data.iter_mut();
    while let Some(x) = mut_items.next() {
        if *x % 2 == 0 {
            let slice = mut_items.into_slice();
            *x += *slice.iter().find(|&x| x % 3 == 0).unwrap();
            mut_items = slice.iter_mut();
        }
    }
}

println!("{:?}", data);

gives

[1, 5, 3, 10, 5, 15, 7, 17, 9, 22, ...]

as with Matthieu M.'s solution.

The key is to use mut_items.into_slice() to "reborrow" the iterator, effectively producing a local (and thus safe) clone of the iterator.

like image 139
Veedrac Avatar answered Oct 26 '22 10:10

Veedrac