-
Notifications
You must be signed in to change notification settings - Fork 14k
Implement partial_sort_unstable for slice #149318
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
base: main
Are you sure you want to change the base?
Conversation
This comment has been minimized.
This comment has been minimized.
7af04ad to
115ac5c
Compare
This comment has been minimized.
This comment has been minimized.
Signed-off-by: tison <wander4096@gmail.com>
115ac5c to
0e87d5d
Compare
Signed-off-by: tison <wander4096@gmail.com>
|
cc @orlp |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left some remarks, some on style, but also some with substance.
Besides comments on the code that's written, I do note a lack of tests?
| /// as if the whole slice were sorted in ascending order. | ||
| /// | ||
| /// This sort is unstable (i.e., may reorder equal elements), in-place (i.e., does not | ||
| /// allocate), and *O*(*n* + *k* \* log(*k*)) worst-case. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not specified what k is.
| /// | ||
| /// If the implementation of [`Ord`] for `T` does not implement a [total order], the function | ||
| /// may panic; even if the function exits normally, the resulting order of elements in the slice | ||
| /// is unspecified. See also the note on panicking below. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need to repeat the entire comment with examples from sort_unstable_by here, I think we can just refer the reader to its comment. This concerns this paragraph as well as all following paragraphs up until # Panics.
| where | ||
| F: FnMut(&T, &T) -> Ordering, | ||
| R: RangeBounds<usize>, | ||
| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this implementation should be under sort::unstable::partial_sort instead, and like its cousin sort::unstable::sort take a function returning a boolean. Then partial_sort_unstable(_by(_key)) can all dispatch to that one directly.
| /// Partially sorts the slice in ascending order **without** preserving the initial order of equal elements. | ||
| /// | ||
| /// Upon completion, the elements in the specified `range` will be the elements of the slice | ||
| /// as if the whole slice were sorted in ascending order. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is missing the guarantees I mentioned in my comment on the ACP about the elements that come before and after the sorted range.
| let Range { start, end } = slice::range(range, ..len); | ||
|
|
||
| if start + 1 > end { | ||
| // target range is empty, nothing to do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is incorrect if we do provide the guarantees for elements before and after the range I mentioned in my comment on the ACP. I think those guarantees are more useful than allowing the partial sort by an empty range in the middle to be a no-op.
| let len = self.len(); | ||
| let Range { start, end } = slice::range(range, ..len); | ||
|
|
||
| if start + 1 > end { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What a very strange way to write start == end. slice::range already disallows inverted ranges.
| return; | ||
| } | ||
|
|
||
| let index = start; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think assigning start to a variable which is used only once and is later shadowed with a different definition is not a good idea. Just directly pass start to partition_at_index IMO.
| let (_, _, rest) = | ||
| sort::select::partition_at_index(self, index, |a, b| compare(a, b) == Less); | ||
|
|
||
| if start + 2 > end { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, very strange way to write end - start == 1. I think this branch is worthwhile though, select_nth_unstable does guarantee that this singular element is in its correct place.
This refers to #149046.