TimY
TimY

Reputation: 5416

How to implement drop_while on mutable iterator?

Is there an efficient way to perform a drop_while for mutable iterators?

Using .take_while() on its own is insufficient because TakeWhile is lazy:

let s = String::from("abcdefg");
let mut it = s.chars();

it.by_ref().take_while(|x| *x != 'c');

println!("{:?}", it.next());

This results in a Some('a') and the following warning:

unused `std::iter::TakeWhile` that must be used

This can be fixed by running a .collect() which results in the wanted Some('d'):

let _: String = it.by_ref().take_while(|x| *x < 'c').collect();

But, is this the correct approach? Would this not waste resources?

Upvotes: 0

Views: 1033

Answers (2)

Peter Hall
Peter Hall

Reputation: 58785

You can use skip_while:

let x = it.by_ref().skip_while(|x| *x <= 'c').next();
println!("{:?}", x); // Some('d')

which is equivalent to using find, with a negated predicate:

let x = it.by_ref().find(|x| *x > 'c');
println!("{:?}", x); // Some('d')

Upvotes: 2

pretzelhammer
pretzelhammer

Reputation: 15135

I believe most iterator methods are lazy except for for_each which seems to be eager. You can turn your take_while into a drop_while like this:

fn main() {
    let s = String::from("abcdefg");
    let mut it = s.chars();
    
    it.by_ref().take_while(|x| *x != 'c').for_each(drop);
    
    println!("{:?}", it.next()); // prints "Some('d')"
}

playground

Upvotes: 0

Related Questions