TL ; DR:
To sort by your own rule, give sort_by a closure. It compares two items with cmp.
let mut nums = vec![25, 13, 5, 41, 33];
nums.sort_by(|a, b| (a % 10).cmp(&(b % 10)).then(a.cmp(b)));
// [41, 13, 33, 5, 25]
let mut scores = vec![70, 95, 82];
scores.sort_by(|a, b| b.cmp(a));
// [95, 82, 70]
Full lesson:
You met sort() in the Shopping Cart project. It sorts a Vec from small to large, or from A to Z. Sometimes you need another order. The shortest word may have to come first, or the highest score.
Then use sort_by with a closure, as you wrote in Vec & Iterators. The closure gets two items, a and b. It returns how they compare.
The cmp method compares two values. It gives an Ordering. That is Less, Equal or Greater. With Less, a goes first.
- Low to high:
a.cmp(b). - High to low:
b.cmp(a). Swapping the two flips the order. - Shortest first:
a.len().cmp(&b.len()).
For two rules, chain them with then. The second comparison only counts when the first one is Equal.
Above, the first rule compares the last digits, a % 10 and b % 10. Numbers with the same last digit then go from small to large.
For one rule, sort_by_key is shorter. Its closure returns what to sort by, as in words.sort_by_key(|w| w.len()).
The sort_by method sorts the Vec itself, so it must be mut. To keep the original, sort a copy made with clone().
Your task
A pet shop sells toys. Their prices are in prices. Sort prices from high to low.
The shop's pets are in names. Sort names by their last letter, in alphabetical order. Names with the same last letter go from A to Z.
The code already prints both, one item per line.
Expected output:
30
12
8
5
Bella
Luna
Bo
Coco
Max
RexFree plan: 30 tutor messages. PRO is unlimited.
