【发布时间】:2022-01-30 22:51:32
【问题描述】:
我有一个向量[(5, 1), (9, 1), (4, 2)]
我希望它被排序为[(4, 2), (9, 1), (5, 1)]
按第二个元素然后第一个元素的降序排列。
可以使用sort_by(|x, y| y.cmp(x))函数吗?
【问题讨论】:
我有一个向量[(5, 1), (9, 1), (4, 2)]
我希望它被排序为[(4, 2), (9, 1), (5, 1)]
按第二个元素然后第一个元素的降序排列。
可以使用sort_by(|x, y| y.cmp(x))函数吗?
【问题讨论】:
这当然是可能的,而且您使用sort_by 的想法是正确的。您可以按照您建议的方式按第二个元素进行排序。
sort_by(|x, y| y.1.cmp(&x.1))
这解决了您问题的第一部分。为了处理决胜局,我们希望能够说“如果第二个元素相同,则通过第一个元素”,事实上,Rust 有一个方法可以做到这一点:Ordering::then。
sort_by(|x, y| y.1.cmp(&x.1).then(y.0.cmp(&x.0)))
注意:这将在每种情况下评估两个排序,这可能没问题。如果您的比较函数异常昂贵,您可以考虑使用then_with,它以闭包而不是值作为参数。
【讨论】:
Copy 类型时,我建议改用v.sort_by_key(|&(_, x)| std::cmp::Reverse(x));,这样更清楚。 (对于非Copy 类型,sort_by_key 存在一些生命周期问题,并且更难使用)
这是一种方法:
ve.sort_unstable_by(|a, b| (b.1, b.0).cmp(&(a.1, a.0)));
请注意,我使用了sort_unstable_by(),在您的情况下,它的效果与sort_by() 相同,但速度更快,占用的内存更少。
Silvio 的建议也可以通过使用sort_unstable_by 进行轻微优化:
ve.sort_unstable_by(|x, y| y.1.cmp(&x.1).then(y.0.cmp(&x.0)));
我想到了另外一种方法:
ve.sort_unstable_by_key(|k| (-k.1, -k.0));
【讨论】:
|a, b| (&b.1, &b.0).cmp(&(&a.1, &a.0))
ve.sort_unstable_by_key(|&(x, y)| Reverse((y, x))),使用std::cmp::Reverse。使用否定以相反的顺序排序似乎有点 hack。