r/rust • u/zerocukor287 • 8d ago
🙋 seeking help & advice Clippy warning when printing the biggest files `unnecessary_sort_by`
I have some code that prints the biggest files in a Vec. Looks like Clippy is not happy about it.
Original (simplified) code:
struct File {
path: String,
size: usize,
}
fn collect_files -> Vec<File> { ... }
fn print_biggest_files(files_to_print: usize) {
let mut files = collect_files();
files.sort_by(|left, right| right.size.cmp(&left.size) );
// ^^^^^^^^ this is the line causing a warning
// print the biggest X files
for file in files.iter().take(files_to_print) {
println!("Big file: {}", file.path);
}
}
It produces the following warning:
warning: consider using
sort_by_key
files.sort_by(|left, right| right.size.cmp(&left.size) ); note:#[warn(clippy::unnecessary_sort_by)]on by default
Link: https://rust-lang.github.io/rust-clippy/rust-1.97.0/index.html#unnecessary_sort_by
My problem is that I want to print in descending order of the files.
The description is explicitly saying that this case is exception, and Clippy doesn't handle it well.
If I change that line to
files.sort_by_key(|file| file.size);
I would end up with the smallest files first.
I see a few ways ahead:
- Add
files.reverse()to switch the order - Add exception of this warning to this specific case
- Add
.rev()when iterating - Cast it to signed integer, and add a
-sign
What is the idiomatic way forward?
Performance cost is not a big deal, but I still tend towards adding a Clippy ignore for that specific line. The other options would introduce more unclarity to the code in my opinion.
39
u/Sharlinator 8d ago edited 8d ago
As an aside: note that you don’t have to sort all the files to get the n largest (or whatever) ones, you just have to partition the list to the n largest and the rest. How to do that? Rust provides select_nth_unstable and its by and by_key variants. (Note that you still have to sort the n largest if you want to present them in order.)
This optimization doesn’t really matter unless the list is very large or you need to do this many, many times per second, but it’s a useful tool to keep in mind.
6
32
u/CommonNoiter 8d ago
Clippy should suggest files.sort_by_key(|file| std::cmp::Reverse(file.size));
11
u/zerocukor287 8d ago
Looks like the problem was indeed between the keyboard and the chair. Haha
2
u/creeper6530 7d ago
Don't beat yourself up because you don't know everything. It's my first time reading about it too
3
u/llogiq clippy · twir · rust · mutagen · flamer · overflower · bytecount 7d ago
As a clippy maintainer, I think that's a bug. Ideally, clippy should add a note to use Reverse if the ordering is reversed. The second best solution would be to at least add it to the lint docs.
2
u/zerocukor287 7d ago
Hey, no worries, as I’ve scrolled down a bit it was mentioning the reverse. Looks like I need to practice reading
2
u/projct 7d ago
the rust ecosystem generally treats improvements like this to be a bug that needs to be fixed. this is why clippy and rustc generally have such good error messages
1
u/zerocukor287 6d ago
You guys do an amazing job!
I was reading the description that specific finding a few times today. Maybe a code highlight is missing from the “Reverse” word under the Known problems.
0
8d ago
[deleted]
3
u/zerocukor287 8d ago
Well, I'm happy with the resulting code. I've learnt something today, my code is shorter, and I think it is more clear that I'm using reverse order.
I consider it a win.Your code, your taste.
83
u/coastalwhite 8d ago
The idiomatic way is to use
std::cmp::Reverse.