918-iterator-nth — Iterator nth
Tutorial
The Problem
Accessing the nth element of an iterator requires consuming all preceding elements — the iterator has no random access. Iterator::nth(n) does exactly this: it skips n elements and returns the (n+1)th as Option<T>. For slices, .get(n) is O(1) and preferred. For filtered or chained iterators, .nth() provides controlled positional access without collecting. Understanding nth's consumption semantics — it advances the iterator past n elements — is essential for using it correctly in parsing and protocol implementations.
🎯 Learning Outcomes
.nth(n) to access the nth element of an iterator, consuming 0..n.nth() advances the iterator — subsequent calls continue from after the consumed positionNone safely for out-of-bounds access.get(n) as the O(1) alternative when availableList.nth which raises on out-of-boundsCode Example
#![allow(clippy::all)]
//! 279. Random access with nth()
//!
//! `nth(n)` returns `Option<T>` at index n, consuming elements 0..n in the process.
#[cfg(test)]
mod tests {
#[test]
fn test_nth_basic() {
let v = [10i32, 20, 30, 40];
assert_eq!(v.iter().nth(2), Some(&30));
}
#[test]
fn test_nth_out_of_bounds() {
let v = [1i32, 2];
assert_eq!(v.iter().nth(5), None);
}
#[test]
fn test_nth_advances_iterator() {
let mut it = [1i32, 2, 3, 4, 5].iter();
assert_eq!(it.nth(1), Some(&2)); // consumes 1,2
assert_eq!(it.nth(0), Some(&3)); // now at 3
}
#[test]
fn test_nth_zero() {
let v = [99i32];
assert_eq!(v.iter().nth(0), Some(&99));
}
}Key Differences
.nth() advances the iterator — it is a cursor operation; OCaml List.nth_opt always starts from the beginning of the list.Option<T> for out-of-bounds; OCaml List.nth raises — use List.nth_opt for safe access..get(n) is O(1) in Rust, Array.get arr i is O(1) in OCaml.it.nth(0); it.nth(0); it.nth(0) accesses elements 0, 1, 2 sequentially; OCaml List.nth_opt xs 0; List.nth_opt xs 1; List.nth_opt xs 2 accesses 0, 1, 2 independently.OCaml Approach
List.nth: 'a list -> int -> 'a raises Not_found or Invalid_argument on out-of-bounds — not safe. List.nth_opt: 'a list -> int -> 'a option (since 4.05) is the safe version. Both are O(n). Array.get: 'a array -> int -> 'a raises on bounds; Array.get with bounds check is O(1). Unlike Rust's .nth(), OCaml's does not advance a cursor — each call to List.nth starts from the beginning.
Full Source
#![allow(clippy::all)]
//! 279. Random access with nth()
//!
//! `nth(n)` returns `Option<T>` at index n, consuming elements 0..n in the process.
#[cfg(test)]
mod tests {
#[test]
fn test_nth_basic() {
let v = [10i32, 20, 30, 40];
assert_eq!(v.iter().nth(2), Some(&30));
}
#[test]
fn test_nth_out_of_bounds() {
let v = [1i32, 2];
assert_eq!(v.iter().nth(5), None);
}
#[test]
fn test_nth_advances_iterator() {
let mut it = [1i32, 2, 3, 4, 5].iter();
assert_eq!(it.nth(1), Some(&2)); // consumes 1,2
assert_eq!(it.nth(0), Some(&3)); // now at 3
}
#[test]
fn test_nth_zero() {
let v = [99i32];
assert_eq!(v.iter().nth(0), Some(&99));
}
}#[cfg(test)]
mod tests {
#[test]
fn test_nth_basic() {
let v = [10i32, 20, 30, 40];
assert_eq!(v.iter().nth(2), Some(&30));
}
#[test]
fn test_nth_out_of_bounds() {
let v = [1i32, 2];
assert_eq!(v.iter().nth(5), None);
}
#[test]
fn test_nth_advances_iterator() {
let mut it = [1i32, 2, 3, 4, 5].iter();
assert_eq!(it.nth(1), Some(&2)); // consumes 1,2
assert_eq!(it.nth(0), Some(&3)); // now at 3
}
#[test]
fn test_nth_zero() {
let v = [99i32];
assert_eq!(v.iter().nth(0), Some(&99));
}
}
Exercises
.nth() to implement a simple command-line argument parser that reads options at specific positions in a Vec<String>.every_third<T: Clone>(data: &[T]) -> Vec<T> using a loop calling .nth(2) repeatedly (advancing by 3 each time).parse_protocol(bytes: &[u8]) -> Option<(u8, u16, Vec<u8>)> using iter.nth() to read (version, length, payload) fields.