277: Counting Elements with count()
Functional Programming
Tutorial
The Problem
Counting elements — total count, conditional count, count of distinct values — is one of the most frequent operations in data processing. While len() is available for sized collections, count() works on any iterator, including those from lazy chains of filter(), map(), and flat_map(). It consumes the iterator in a single pass, returning the total number of elements yielded.
🎯 Learning Outcomes
count() consumes the iterator and returns the number of elements as usizefilter().count() as the idiomatic way to count elements satisfying a conditioncount() on sized collections may not call next() at all (size hint optimization)count() with other reductions like sum() for multi-statistic computationCode Example
#![allow(clippy::all)]
//! 277. Counting with count()
//!
//! `count()` consumes an iterator and returns the total number of elements.
#[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
count() on ExactSizeIterator types may return the known size without iteration; OCaml's List.length always traverses the list.count() is the terminal operation in a pipeline; OCaml's equivalent requires wrapping in fold_left or filter + length.size_hint() for count() optimization on known-size iterators but always processes unknown-size ones fully.OCaml Approach
OCaml uses List.length for full list length, and List.length (List.filter pred xs) or List.fold_left with a counter for conditional counting:
let count pred xs = List.fold_left (fun acc x -> if pred x then acc + 1 else acc) 0 xs
let evens = count (fun x -> x mod 2 = 0) (List.init 10 (fun i -> i+1)) (* 5 *)
The fold-based approach avoids building a filtered list just to count it — matching Rust's single-pass filter().count().
Full Source
#![allow(clippy::all)]
//! 277. Counting with count()
//!
//! `count()` consumes an iterator and returns the total number of elements.
#[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);
}
}
✓ Tests
Rust test suite
#[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
filter() and count().HashMap updated via iteration, without using count() directly.count() and fold(0, |acc, _| acc + 1) produce identical results on the same iterator.