ExamplesBy LevelBy TopicLearning Paths
277 Intermediate

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

  • • Understand that count() consumes the iterator and returns the number of elements as usize
  • • Use filter().count() as the idiomatic way to count elements satisfying a condition
  • • Recognize that count() on sized collections may not call next() at all (size hint optimization)
  • • Combine count() with other reductions like sum() for multi-statistic computation
  • Code 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

  • Efficiency: Rust's count() on ExactSizeIterator types may return the known size without iteration; OCaml's List.length always traverses the list.
  • Composability: count() is the terminal operation in a pipeline; OCaml's equivalent requires wrapping in fold_left or filter + length.
  • No size hint in closures: Rust respects size_hint() for count() optimization on known-size iterators but always processes unknown-size ones fully.
  • Use cases: Log analysis (count warnings), test coverage (count assertions), statistics (count non-null values).
  • 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

  • Count the number of words in a string that start with a capital letter using filter() and count().
  • Count the frequency of each character in a string using a HashMap updated via iteration, without using count() directly.
  • Verify that count() and fold(0, |acc, _| acc + 1) produce identical results on the same iterator.
  • Open Source Repos