Iterators

position() and rposition()

The .position() and .rposition() consumer methods search an iterator for the first (or last) element satisfying a predicate FnMut(Self::Item) -> bool and return its zero-based index as Option<usize>.

Signatures and Requirements

fn position<P>(&mut self, predicate: P) -> Option<usize>
where
    Self: Sized,
    P: FnMut(Self::Item) -> bool;

fn rposition<P>(&mut self, predicate: P) -> Option<usize>
where
    P: FnMut(Self::Item) -> bool,
    Self: ExactSizeIterator + DoubleEndedIterator,
Method Search Direction Trait Requirements on Self Returns
.position(p) Front to back (next()) Iterator First matching index Some(i) or None
.rposition(p) Back to front (next_back()) ExactSizeIterator + DoubleEndedIterator Last matching index Some(i) (still 0-indexed from the front) or None

Why does .rposition() require ExactSizeIterator? Because it steps backward from the end using .next_back(), it must know the total length of the iterator upfront to compute the 0-based offset from the front.

Finding First and Last Matching Indices

fn main() {
    let statuses = [200_u16, 500, 200, 503, 200];

    let first_error = statuses.iter().position(|&code| code >= 500);
    let last_error = statuses.iter().rposition(|&code| code >= 500);
    let not_found = statuses.iter().position(|&code| code == 404);

    println!("First 5xx index: {first_error:?}");
    println!("Last 5xx index:  {last_error:?}");
    println!("404 index:       {not_found:?}");
}
First 5xx index: Some(1)
Last 5xx index:  Some(3)
404 index:       None
Index:     0     1     2     3     4
Values: [ 200,  500,  200,  503,  200 ]
                 ▲           ▲
     position ───┘           └─── rposition (steps from back, reports index 3)

Slicing Around a Matched Index

Because .position() returns a usize index, it pairs naturally with slice splitting (.split_at() or range indexing):

fn parse_key_value(line: &str) -> Option<(&str, &str)> {
    let eq_idx = line.bytes().position(|b| b == b'=')?;
    Some((&line[..eq_idx], &line[eq_idx + 1..]))
}

fn main() {
    println!("{:?}", parse_key_value("DATABASE_URL=postgres://localhost/db"));
}
Some(("DATABASE_URL", "postgres://localhost/db"))