在浮点数向量上使用 max_by_key

jay*_*elm 3 iterator vector max rust

我想使用基于某个键max_by_key从f64s的向量中获取最大值。这是一个简单的例子,用一个小向量abs作为关键:

let a: Vec<f64> = vec![-3.0, 0.2, 1.4];
*a.iter().max_by_key(|n| n.abs()).unwrap()
Run Code Online (Sandbox Code Playgroud)

但是,由于f64没有实现Ord,我得到

let a: Vec<f64> = vec![-3.0, 0.2, 1.4];
*a.iter().max_by_key(|n| n.abs()).unwrap()
Run Code Online (Sandbox Code Playgroud)

同样,sort_by_key失败并出现相同的错误:

a.sort_by_key(|n| n.abs())
Run Code Online (Sandbox Code Playgroud)

我知道我可以绕过偏序限制来对浮点数向量进行排序 sort_by

b.sort_by(|m, n| m.partial_cmp(n).unwrap_or(Less))
Run Code Online (Sandbox Code Playgroud)

但这必须在一个向量上调用b,我已经abs为 的每个元素计算了键(在这种情况下)a,然后我必须返回并找到 的相应元素a,这看起来既复杂又缓慢。随着列表中项目数量的增加,我想尽量减少通过数据的次数。

有什么解决方法吗?

mal*_*rbo 5

如果您不想创建包装器类型,您可以使用ordered_float或ord_subset crate。例如

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
}
Run Code Online (Sandbox Code Playgroud)