916-iterator-count — Iterator Count
Tutorial Video
Text description (accessibility)
This video demonstrates the "916-iterator-count — Iterator Count" functional Rust example. Difficulty level: Intermediate. Key concepts covered: Functional Programming. Counting how many elements satisfy a condition is a fundamental operation: how many words are longer than 5 characters, how many numbers are prime, how many transactions exceeded a threshold. Key difference from OCaml: 1. **Single pass**: Rust `.filter().count()` is a single traversal; OCaml `List.filter + List.length` is two passes over the data.
Tutorial
The Problem
Counting how many elements satisfy a condition is a fundamental operation: how many words are longer than 5 characters, how many numbers are prime, how many transactions exceeded a threshold. Rust's Iterator::count() consumes the iterator and returns the number of elements. Combined with .filter(), it counts matching elements. For slices, .len() is O(1) and preferred; for filtered or transformed iterators, .count() is the correct consumer. OCaml uses List.length (List.filter pred xs) — two passes — while Rust's .filter().count() is a single pass.
🎯 Learning Outcomes
.count() to consume an iterator and return the element count.filter().count() for conditional counting in one pass.len() (O(1) for slices) is preferred over .count()count() after transformations that change element count (flat_map, filter)List.length (List.filter ...) two-pass approachCode Example
//! 277. Counting with count()
//!
//! `count()` consumes an iterator and returns the total number of elements.
fn main() {
let nums: Vec<i32> = (1..=10).collect();
println!("Count: {}", nums.len());
let even_count = nums.iter().filter(|&&x| x % 2 == 0).count();
println!("Even count: {}", even_count);
let s = "hello world";
let vowels = s.chars().filter(|c| "aeiou".contains(*c)).count();
println!("Vowels in '{}': {}", s, vowels);
let text = "the quick brown fox jumps over the lazy dog";
println!("Word count: {}", text.split_whitespace().count());
// Efficient count for Range (ExactSizeIterator — O(1))
let range_count = (0usize..1_000_000).count();
println!("Range count: {}", range_count);
let sorted = [1i32, 3, 5, 7, 9, 11, 13];
let under_10 = sorted.iter().take_while(|&&x| x < 10).count();
println!("Elements < 10: {}", under_10);
}
#[cfg(test)]
mod tests {
#[test]
fn test_count_basic() {
assert_eq!((1..=10).count(), 10);
}
#[test]
fn test_count_filter() {
let evens = (1..=10).filter(|x| x % 2 == 0).count();
assert_eq!(evens, 5);
}
#[test]
fn test_count_empty() {
let empty: Vec<i32> = vec![];
assert_eq!(empty.iter().count(), 0);
}
#[test]
fn test_count_string_chars() {
let vowels = "hello".chars().filter(|c| "aeiou".contains(*c)).count();
assert_eq!(vowels, 2);
}
}Key Differences
.filter().count() is a single traversal; OCaml List.filter + List.length is two passes over the data..len() (slice) from O(n) .count() (iterator); OCaml List.length is always O(n).List.count pred xs; Rust's iterator method is universally available..take_while().count() safely bounds counting over infinite ranges; OCaml requires explicit Seq.take_while.OCaml Approach
List.length: 'a list -> int counts all elements. List.filter then List.length for conditional count: List.length (List.filter (fun x -> x mod 2 = 0) xs) — two passes. List.fold_left (fun acc x -> if pred x then acc + 1 else acc) 0 xs — single pass. Array.fold_left similarly. Standard OCaml lacks a List.count function — it must be expressed as filter+length or fold.
Full Source
//! 277. Counting with count()
//!
//! `count()` consumes an iterator and returns the total number of elements.
fn main() {
let nums: Vec<i32> = (1..=10).collect();
println!("Count: {}", nums.len());
let even_count = nums.iter().filter(|&&x| x % 2 == 0).count();
println!("Even count: {}", even_count);
let s = "hello world";
let vowels = s.chars().filter(|c| "aeiou".contains(*c)).count();
println!("Vowels in '{}': {}", s, vowels);
let text = "the quick brown fox jumps over the lazy dog";
println!("Word count: {}", text.split_whitespace().count());
// Efficient count for Range (ExactSizeIterator — O(1))
let range_count = (0usize..1_000_000).count();
println!("Range count: {}", range_count);
let sorted = [1i32, 3, 5, 7, 9, 11, 13];
let under_10 = sorted.iter().take_while(|&&x| x < 10).count();
println!("Elements < 10: {}", under_10);
}
#[cfg(test)]
mod tests {
#[test]
fn test_count_basic() {
assert_eq!((1..=10).count(), 10);
}
#[test]
fn test_count_filter() {
let evens = (1..=10).filter(|x| x % 2 == 0).count();
assert_eq!(evens, 5);
}
#[test]
fn test_count_empty() {
let empty: Vec<i32> = vec![];
assert_eq!(empty.iter().count(), 0);
}
#[test]
fn test_count_string_chars() {
let vowels = "hello".chars().filter(|c| "aeiou".contains(*c)).count();
assert_eq!(vowels, 2);
}
}#[cfg(test)]
mod tests {
#[test]
fn test_count_basic() {
assert_eq!((1..=10).count(), 10);
}
#[test]
fn test_count_filter() {
let evens = (1..=10).filter(|x| x % 2 == 0).count();
assert_eq!(evens, 5);
}
#[test]
fn test_count_empty() {
let empty: Vec<i32> = vec![];
assert_eq!(empty.iter().count(), 0);
}
#[test]
fn test_count_string_chars() {
let vowels = "hello".chars().filter(|c| "aeiou".contains(*c)).count();
assert_eq!(vowels, 2);
}
}
Exercises
count_by_key<T, K: Eq + Hash>(data: &[T], key: impl Fn(&T) -> K) -> HashMap<K, usize> using a single pass over the data.count_runs(data: &[i32]) -> usize that counts the number of runs of consecutive equal elements using windows.