# Mini-RFC: min_max

I’m in a need to find the minimum and the maximum in a slice. I could solve this by using the `min` and `max` functions after each other, but this will iterate over the slice twice, which is not optimal.

Instead, I think the solution would be to get both in only one iteration. The signature would be similar to this:

``````trait Iterator {
fn min_max(self) -> (Option<Self::Item>, Option<Self::Item>);
fn min_max_by<F>(self, compare: F) -> (Option<Self::Item>, Option<Self::Item>)
where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering;
fn min_max_by_key<B: Ord, F>(self, f: F) -> (Option<Self::Item>, Option<Self::Item>)
where Self: Sized, F: FnMut(&Self::Item) -> B;
}
``````

What do you think about this? Is this practical? Am I overseeing something? Is this just a special case not not generaly appliable?

As far as I understand, this doesn’t need an official RFC, but can be done via a PullRequest. Am I correct?

1 Like

An interesting quirk of the API is that you’ll need to specifically handle the case where iterator contains a single element only.

3 Likes

Do you? Why don’t return that element twice? It is the min and the max at the same time. I don’t see a contradiction at all.

A solution with a fold looks a bit hairy:

``````fn main() {
let data = [10, 80, 30, 50];

let (min, max) =
data
.iter()
.cloned()
.fold(None, |m: Option<(u32, u32)>, x|
m.map_or(Some((x, x)), |(m1, m2)| Some((m1.min(x), m2.max(x)))))
.unwrap();
println!("{} {}", min, max);
}``````

You’ll need a `T: Clone` for that.

1 Like

True. Okay, I see the special need for the one element case.

Right, I don’t like hairy solutions, I like rusty solutions

So, there is a little chance to get this implemented, because Itertools already implements it (and because of that special case, one could avoid with an enum)?

1 Like

did you look at the itertools link? that’s exactly what it does.

That’s why i wrote that

My intuition is that the “it needs a new special-purpose enum” part might actually be the roughest bit – it opens a huge hole for bikeshedding, which isn’t necessarily fatal, but does mean it’s harder to be confident that the API is the right one to commit to for perpetuity.