ExamplesBy LevelBy TopicLearning Paths
916 Intermediate

916-iterator-count — Iterator Count

Functional Programming

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

  • • Use .count() to consume an iterator and return the element count
  • • Combine .filter().count() for conditional counting in one pass
  • • Understand when .len() (O(1) for slices) is preferred over .count()
  • • Use count() after transformations that change element count (flat_map, filter)
  • • Compare with OCaml's List.length (List.filter ...) two-pass approach
  • Code 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

  • Single pass: Rust .filter().count() is a single traversal; OCaml List.filter + List.length is two passes over the data.
  • len vs count: Rust distinguishes O(1) .len() (slice) from O(n) .count() (iterator); OCaml List.length is always O(n).
  • No standard count: OCaml standard library has no List.count pred xs; Rust's iterator method is universally available.
  • Infinite safety: Rust .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);
        }
    }
    ✓ 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

  • Implement count_by_key<T, K: Eq + Hash>(data: &[T], key: impl Fn(&T) -> K) -> HashMap<K, usize> using a single pass over the data.
  • Write count_runs(data: &[i32]) -> usize that counts the number of runs of consecutive equal elements using windows.
  • Find the length of the longest run of consecutive primes in the first 1000 natural numbers using count with take_while.
  • Open Source Repos