leo848
leo848

Reputation: 667

Is there an iterator method that takes a predicate and gives back an index and the matching element?

I am searching for something like this:

let iter = vec![1, 2, 40, 3].into_iter();
let (pos, elt) = iter.position_find(|&x| x > 10);
//                    ^ does not exist

println!("{pos} {elt}"); // 2 40

Both Iterator::position and Iterator::find advance the iterator, so I can't use both unless I'm cloning the iterator, which is unnecessary here.

Upvotes: 0

Views: 1196

Answers (1)

isaactfa
isaactfa

Reputation: 6651

You can use find together with enumerate:

let iter = vec![1, 2, 40, 3].into_iter();
if let Some((pos, elt)) = iter.enumerate().find(|(i, x)| x > &10) {
    println!("{pos} {elt}"); // 2 40
}

If you don't want to write this out every time, you could even turn it into an extension trait to automatically implement it as a method on all iterators:

trait FindPosition: Iterator {
    fn find_position<F: FnMut(usize, &Self::Item) -> bool>(
        &mut self,
        mut f: F,
    ) -> Option<(usize, Self::Item)> {
        self.enumerate().find(|(i, item)| f(*i, item))
    }
}

impl<I: Iterator> FindPosition for I {}

fn main() {
    let mut iter = vec![1, 2, 40, 3].into_iter();
    if let Some((pos, elt)) = iter.find_position(|_, x| *x > 10) {
        println!("{pos} {elt}"); // 2 40
    }
}

Upvotes: 3

Related Questions