我想使用max_by_key
根据某个键从f64
s的向量中获取最大值。这是一个简单的示例,带有一个小向量,并以abs
为键:
let a: Vec<f64> = vec![-3.0, 0.2, 1.4];
*a.iter().max_by_key(|n| n.abs()).unwrap()
但是,由于f64
没有实现Ord
,我得到了
error[E0277]: the trait bound `f64: std::cmp::Ord` is not satisfied
--> src/main.rs:3:15
|
3 | *a.iter().max_by_key(|n| n.abs()).unwrap();
| ^^^^^^^^^^ the trait `std::cmp::Ord` is not implemented for `f64`
同样,sort_by_key
失败并出现同样的错误:
a.sort_by_key(|n| n.abs())
我知道我可以解决部分排序限制,用sort_by
b.sort_by(|m, n| m.partial_cmp(n).unwrap_or(Less))
但是必须在向量b
上调用,我为abs
的每个元素计算了密钥(在本例中为a
),然后我会必须返回并找到a
的相应元素,这似乎复杂而缓慢。随着列表中项目数量的增加,我希望最大限度地减少数据传递。
有没有解决方法?
答案 0 :(得分:2)
如果您不想创建包装类型,可以使用ordered_float或ord_subset包。例如
extern crate ordered_float;
extern crate ord_subset;
#[test]
fn test_example_() {
use ordered_float::OrderedFloat;
// OrderedFloat -> NaN is greater than all other values and equal to itself.
// NotNaN -> NotNaN::new panics if called with NaN.
let mut a: Vec<f64> = vec![-3.0, 0.2, 1.4];
let max = *a.iter().max_by_key(|n| OrderedFloat(n.abs())).unwrap();
assert_eq!(-3.0, max);
a.sort_by_key(|n| OrderedFloat(n.abs()));
assert_eq!(vec![0.2, 1.4, -3.0], a);
}
#[test]
fn test_example_ord_subset() {
use ord_subset::OrdSubsetIterExt;
let a: Vec<f64> = vec![-3.0, 0.2, 1.4];
// For f64, NaN is ignored.
let max = *a.iter().ord_subset_max_by_key(|n| n.abs()).unwrap();
assert_eq!(-3.0, max);
// ord_subset does not help with the sorting problem in the question
}