0

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.

Makyen
  • 31,849
  • 12
  • 86
  • 121
leo848
  • 637
  • 2
  • 7
  • 24

1 Answers1

3

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
    }
}
isaactfa
  • 5,461
  • 1
  • 10
  • 24