Skip to content

Added minmax function. #11789

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 1, 2014
Merged

Added minmax function. #11789

merged 1 commit into from
Feb 1, 2014

Conversation

pongad
Copy link
Contributor

@pongad pongad commented Jan 25, 2014

All tests passing. #5268

@@ -882,6 +882,15 @@ pub trait OrdIterator<A> {
/// assert!(a.iter().min().unwrap() == &1);
/// ```
fn min(&mut self) -> Option<A>;

/// `minmax` finds the mininum and maximum elements in the vector.
/// The return type `MinMaxResult` is an enum of three variants.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you put an empty line before this sentence? rustdoc will take the first paragraph as the summary, and I think just the first line is appropriate.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, it would be worth mentioning that this is more efficient that just min and max, since it does 1.5 comparisions on average.

And, these 3 points could be a markdown list:

The return type `MinMaxResult` is an enum of three variants:
- `NoElements` is returned ...
- `OneElement(x)` is returned ...
- ...

@pongad
Copy link
Contributor Author

pongad commented Jan 26, 2014

Fixed comments by @huonw .

@@ -882,6 +882,39 @@ pub trait OrdIterator<A> {
/// assert!(a.iter().min().unwrap() == &1);
/// ```
fn min(&mut self) -> Option<A>;

/// `min_max` finds the mininum and maximum elements in the vector.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/vector/iterator/

@lilyball
Copy link
Contributor

What is the value in using a custom enum with a state for OneElement instead of just using Option and treating the one-element case the same as a two-element case with identical elements (i.e. just return the one element for both min and max)?

@huonw
Copy link
Member

huonw commented Jan 27, 2014

That requires Clone, to duplicate the single element into min and max.

@lilyball
Copy link
Contributor

Fair enough. Perhaps MinMaxResult could implement an .into_option() method when T: Clone, so users can benefit from the normal complement of Option methods if the value is cloneable.

@huonw
Copy link
Member

huonw commented Jan 27, 2014

Maybe, I'm personally not particularly fussed either way.

Also, @pongad, there appears to be a merge commit in the list of commits, it would be good to remove it before merging this PR (rebasing & force pushing is perfectly ok).

@pongad
Copy link
Contributor Author

pongad commented Jan 27, 2014

@kballard I'm a little confused by your suggestion, do you mean returning two Option's? With both None for NoElements, one Some and one None for OneElement, etc?
@huonw Will fix that in the next update.

@lilyball
Copy link
Contributor

@pongad I was suggesting having fn min_max(&mut self) -> Option<A>. @huonw's point about requiring Clone is good, though, so now I'm suggesting having

impl<T: Clone> MinMaxResult<T> {
    fn into_option(self) -> Option<(T, T)> {
        match self {
            NoElements => None,
            OneElement(x) => Some((x.clone(), x)),
            MinMax(a, b) => Some((a, b))
        }
    }
}

Some(x) => x
};
let second = match self.next() {
None => {left_over = Some(first); break;}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not move there the code in "match left_over" and eliminate the left_over variable entirely?

That would slightly shorten the code.

@pongad
Copy link
Contributor Author

pongad commented Jan 29, 2014

@bill-myers We don't know the length of the iterator, so we don't know ahead of time if we need the left_over or not.

@huonw
Copy link
Member

huonw commented Jan 29, 2014

You can inline the match on left_over: i.e. have

let second = match self.next() {
    None => {
        if first < min {
            min = first
        } else if first > max {
            max = first
        }
        break;
    }
}

and just avoid using left_over completely. (It was a silly suggestion from me, sorry.)

Also, you appear to have git troubles: github is telling me that there are 238 changed files. (I've found it easier to just avoid merging entirely, rather than merging and fixing it up later. This also requires avoiding git pull since that merges by default (git fetch + git rebase or git pull --rebase are ok, though).)

@pongad
Copy link
Contributor Author

pongad commented Jan 29, 2014

@huonw I see it now. Sorry, I completely misunderstood. I just fixed the git problem (I think). I'll make the changes and test, will push when ready.

@pongad
Copy link
Contributor Author

pongad commented Jan 31, 2014

Fixed comments from @huonw

/// - `NoElements` if the iterator is empty.
/// - `OneElement(x)` if the iterator has exactly one element.
/// - `MinMax(x, y)` is returned otherwise, where `x <= y`. Two values are equal if and only if
/// there are more than one elements in the iterator and all elements are equal.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think "are more than one elements" is more grammatically correct as "is more than one element".

@lilyball
Copy link
Contributor

Implementation looks good. Thanks for into_option(). r=me if you fix the comments.

@pongad
Copy link
Contributor Author

pongad commented Feb 1, 2014

r=kballard

@pongad
Copy link
Contributor Author

pongad commented Feb 1, 2014

Though, I'm not entirely sure why into_option uses self and not &self. Compilation doesn't like &self, and I'm not quite sure why :(

@lilyball
Copy link
Contributor

lilyball commented Feb 1, 2014

@pongad Taking &self would require cloning all values, rather than the limited single clone for the OneElement() case. It would also be called to_option instead of into_option.

@pongad
Copy link
Contributor Author

pongad commented Feb 1, 2014

@kballard I'm not "fluent" with the way Rust handles borrowing yet, but I think I see what you are saying. That would mean after calling r.into_option(), the original r is rendered useless right? I've also fixed the typo.

@lilyball
Copy link
Contributor

lilyball commented Feb 1, 2014

@pongad Yes, r.into_option() will consume the receiver (it will move it into the method call). And thanks for fixing the typo, we'll see what bors does when it finishes testing the previous version.

bors added a commit that referenced this pull request Feb 1, 2014
@bors bors merged commit d088e5f into rust-lang:master Feb 1, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants