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)returnstrueis extended into the first collection (left). - Every element for which
f(&item)returnsfalseis 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