Is there a way to sort a slice in specifically 'ascending' or 'descending' order?

I need to sort a slice of elements where it is important that the element which compares as 'Greater' than the other elements in the slice ends up at index '0'.

Of course the regular slice::sort family of methods kind of do this in practice but I cannot find anything in any documentation specifying what direction they 'should' order the elements in. I need a function which guarantees either 'ascending' or 'descending' ordering even if the underlying implementation is changed.

1 Like

It's always ascending order (Greater goes last).

For reversing sort there's sort_by, and sort_by_key that can be used with std::cmp::Reverse for small copyable keys.

4 Likes
let mut slice = [...];
slice.sort();
slice.reverse();
2 Likes

I know that they currently do this. But are there any guarantees that they will still do this in future versions of the standard library?

For example, since the stable sorting methods already preserve the ordering of equal elements maybe that is extended to also apply to the direction the elements are sorted in. The function would still behave exactly as specified in the documentation (as far as I understand it).

Of course that probably will never happen and I'd imagine that a lot of peoples' code would break if such an update was made but I hope you get my point.

Mostly I want this for peace of mind and code readability.

We only have what the doc says for guarantees. The doc does guarantee imply ascending order of course (since it uses the Ord or compare fn that return Ordering), and with a reversed key comparison this does give you a guarantee of descending order.

For stable sort it guarantees the order in the slice is not changed for equal elements. That is guaranteed no matter what key comparison you supply -- if that were not true, it would have to be documented. Therefore I don't know what other guarantee you would need.

It's "guaranteed" to be sorted in ascending order unless otherwise specified. While it doesn't hurt to explicitly call this out in the documentation, it is assumed to be "obvious".

There are many cases where documentation isn't precise—welcome to the world of natural language and not precise languages like ZFC. For example, slice::contains states:

Returns true if the slice contains an element with the given value.

Uh oh, doesn't that mean it's possible it always returns true since it's not phrased as a logical biconditional (i.e., "Returns true iff the slice contains an element with the given value")? It's assumed it's understood.

1 Like

Personally I thought the documentation was implying that neither descending or ascending order can be assumed by intentionally not saying anything about it. I mean if it's not the first thing you would want to know about a sorting function then it's at least in the top 5.

If the documentation for a sorting function does not say anything about if it sorts in ascending or descending direction then you should assume that it could be either.

I do not say this to criticize the standard library or the documentation. I can think of a lot of reasons for why they would want to avoid specifying this.

I am just asking if something more explicit exists or if the documentation actually does specify the direction somewhere and I just could not find it (please quote or link it if that is the case).

And if neither of those are true then that is also fine.

2 Likes

Neither are true, as far as I can see.

2 Likes

It's informally implied but not explicitly stated. You can submit a PR that adds this information to the documentation if you feel inclined, and it may be accepted.

You must accept the fact that documentation is not a formal specification though; if not, there is very little documentation that you will be able to use. Again, the fact that slice::contains does not state nor imply that false is returned when the item is not contained in it, doesn't actually mean false isn't returned since it's informally implied. Presumably you don't have an issue with using slice::contains though despite this lack of "guarantee" because it's "obvious" to you (i.e., liar's paradox withstanding, there is always a line; sometimes you will be on the wrong side of this line—as a hyper-logical individual this is frequently true for me—and as long as the line is drawn such that the wrong side of it has a small population, then it's likely it won't be redrawn).

That's not to say I doubt your genuine confusion, but it's just the reality: if very few people are confused by the "direction" of the ordering, then it's reasonable that it's not explicitly stated. Note I'm not claiming that there are very few people that are confused by the "direction" but if there are very few people. Having said that, seeing how that documentation has been around for presumably a very long time without any changes, it's reasonable to think (but not formally prove) that there aren't many people.

The Rust community is pretty welcoming of changes that may not help many people as long as it's simple, so knock yourself out and submit a PR.

1 Like

I do see and agree with your point. The issue I have is that I do not agree that the documentation even informally implies a specific direction.

In the case of slice::contains the function would be useless if it always returned true. Hence the implication that if it returns true when the element is found then it must return false when it isn't.

But slice::sort is completely fine for most uses even if you do not know if the order is 'ascending' or 'descending' in terms of the cmp::Ord trait.

I have personally written a ton of different sorting functions in multiple scenarios where I intentionally did not specify this because it was not worth the overhead of keeping track of when it wasn't needed.

That is to say I might write a PR, but I would also consider it to be completely reasonable for this not to be specified.

1 Like

In the case of slice::contains the function would be useless if it always returned true. Hence the implication that if it returns true when the element is found then it must return false when it isn't.

But slice::sort is completely fine for most uses even if you do not know if the order is 'ascending' or 'descending' in terms of the cmp::Ord trait.

Certainly. I was employing reductio ad absurdum with my slice::contains example to illustrate the point. I agree it's more "reasonable" to be confused by the lack of explicit "direction" in slice::sort.

I have now opened a PR to specify an ascending order in the documentation.

3 Likes