ExamplesBy LevelBy TopicLearning Paths
270 Intermediate

270: Finding Index with position()

Functional Programming

Tutorial

The Problem

Locating the position of an element matching a condition is a fundamental operation: finding where a token appears in a list, locating a delimiter in a byte sequence, or finding the insertion point in a sorted array. Unlike find() which returns the element, position() returns the zero-based index — essential when the index itself is needed for slicing, bounds computation, or further navigation.

🎯 Learning Outcomes

  • • Understand that position(pred) returns Option<usize> — the index of the first matching element
  • • Distinguish position() from find(): index vs element value
  • • Use rposition() to find the last matching index from the right (on slices)
  • • Recognize that position() consumes up to the matching element and stops
  • Code Example

    #![allow(clippy::all)]
    //! 270. Finding index with position()
    //!
    //! `position(pred)` returns `Option<usize>` — index of first element where predicate holds.
    
    #[cfg(test)]
    mod tests {
        #[test]
        fn test_position_found() {
            let v = [10i32, 20, 30, 40];
            assert_eq!(v.iter().position(|&x| x == 30), Some(2));
        }
    
        #[test]
        fn test_position_not_found() {
            let v = [1i32, 2, 3];
            assert_eq!(v.iter().position(|&x| x == 99), None);
        }
    
        #[test]
        fn test_rposition() {
            let v = [1i32, 2, 3, 2, 1];
            assert_eq!(v.iter().rposition(|&x| x == 2), Some(3));
        }
    
        #[test]
        fn test_position_first_occurrence() {
            let v = [5i32, 5, 5];
            assert_eq!(v.iter().position(|&x| x == 5), Some(0));
        }
    }

    Key Differences

  • Return type: Rust returns Option<usize> (index only); OCaml 4.14's Array.find_index returns Option<int * 'a> (index and element).
  • Standard library: position() is built into Rust's Iterator; OCaml required manual implementation or recent library additions.
  • Reverse search: rposition() is available on slice iterators; OCaml requires List.rev then find_index or a right fold.
  • Use cases: Parser delimiter detection, binary search insertion points, finding newlines in byte buffers.
  • OCaml Approach

    OCaml's List.find_index (recent versions) or a manual fold:

    let position pred lst =
      let rec go i = function
        | [] -> None
        | x :: xs -> if pred x then Some i else go (i+1) xs
      in go 0 lst
    

    For arrays, Array.find_index (OCaml 4.14+) returns Option<int * 'a> with both index and element.

    Full Source

    #![allow(clippy::all)]
    //! 270. Finding index with position()
    //!
    //! `position(pred)` returns `Option<usize>` — index of first element where predicate holds.
    
    #[cfg(test)]
    mod tests {
        #[test]
        fn test_position_found() {
            let v = [10i32, 20, 30, 40];
            assert_eq!(v.iter().position(|&x| x == 30), Some(2));
        }
    
        #[test]
        fn test_position_not_found() {
            let v = [1i32, 2, 3];
            assert_eq!(v.iter().position(|&x| x == 99), None);
        }
    
        #[test]
        fn test_rposition() {
            let v = [1i32, 2, 3, 2, 1];
            assert_eq!(v.iter().rposition(|&x| x == 2), Some(3));
        }
    
        #[test]
        fn test_position_first_occurrence() {
            let v = [5i32, 5, 5];
            assert_eq!(v.iter().position(|&x| x == 5), Some(0));
        }
    }
    ✓ Tests Rust test suite
    #[cfg(test)]
    mod tests {
        #[test]
        fn test_position_found() {
            let v = [10i32, 20, 30, 40];
            assert_eq!(v.iter().position(|&x| x == 30), Some(2));
        }
    
        #[test]
        fn test_position_not_found() {
            let v = [1i32, 2, 3];
            assert_eq!(v.iter().position(|&x| x == 99), None);
        }
    
        #[test]
        fn test_rposition() {
            let v = [1i32, 2, 3, 2, 1];
            assert_eq!(v.iter().rposition(|&x| x == 2), Some(3));
        }
    
        #[test]
        fn test_position_first_occurrence() {
            let v = [5i32, 5, 5];
            assert_eq!(v.iter().position(|&x| x == 5), Some(0));
        }
    }

    Exercises

  • Find the index of the first vowel in a string's character iterator using position().
  • Use position() to split a string at the first occurrence of ":" — return None if no colon is found.
  • Find all positions of a value in a slice (not just the first) by using position() iteratively on a shrinking sub-slice, collecting all indices.
  • Open Source Repos