Iterators

partition()

The .partition() consumer consumes an iterator and splits its elements into two collections of the same type B ((B, B)) based on a predicate FnMut(&Self::Item) -> bool.

Signature

fn partition<B, F>(self, f: F) -> (B, B)
where
    Self: Sized,
    B: Default + Extend<Self::Item>,
    F: FnMut(&Self::Item) -> bool,
  • Every element for which f(&item) returns true is extended into the first collection (left).
  • Every element for which f(&item) returns false is extended into the second collection (right).
Source: [ 1, 2, 3, 4, 5, 6 ]
          │  │  │  │  │  │   .partition(|&n| n % 2 == 0)
          │  ├──┼──┤  │  └──> true:  [ 2, 4, 6 ]
          └──┼──┘  └──┼─────> false: [ 1, 3, 5 ]

Splitting Elements into Two Vec<T> Collections

Because .partition() is generic over the output collection type B: Default + Extend<Self::Item>, provide a type annotation on the tuple binding (such as (Vec<_>, Vec<_>)):

fn main() {
    let numbers = [10, 15, 22, 7, 30, 9];

    let (evens, odds): (Vec<i32>, Vec<i32>) = numbers
        .into_iter()
        .partition(|&n| n % 2 == 0);

    println!("Evens: {evens:?}");
    println!("Odds:  {odds:?}");
}
Evens: [10, 22, 30]
Odds:  [15, 7, 9]

Partitioning Result<T, E> Values Without Short-Circuiting

When processing a batch of operations that return Result<T, E>, .collect::<Result<Vec<T>, E>>() stops at the first error. To run all items and separate the Ok values from the Err values, partition by Result::is_ok and unwrap each side:

fn main() {
    let raw = ["42", "bad_1", "100", "bad_2", "7"];

    let (oks, errs): (Vec<_>, Vec<_>) = raw
        .iter()
        .map(|s| s.parse::<i32>())
        .partition(Result::is_ok);

    let values: Vec<i32> = oks.into_iter().map(Result::unwrap).collect();
    let errors: Vec<_> = errs.into_iter().map(Result::unwrap_err).collect();

    println!("Parsed values: {values:?}");
    println!("Failed count:  {}", errors.len());
}
Parsed values: [42, 100, 7]
Failed count:  2