rust 具有比较功能的BTreeMap

xt0899hw  于 2023-01-17  发布在  其他
关注(0)|答案(1)|浏览(163)

我想在Rust中创建BTreeMap,但是为了比较我的键,我需要另一个数据结构,我把它存储在一个变量中。不幸的是,Rust中的traits似乎不能在本地定义,我的Ord实现不能依赖于本地变量。
这是否意味着我必须重新实现整个BTreeMap才能使用lambdas?

tv6aics1

tv6aics11#

虽然这不是最佳的(因为你必须存储额外的数据/指针,可能会搞砸),你可以把局部变量(或者根据大小和引用的情况)和你的值一起存储:

use std::cmp::{PartialOrd, Ord, Ordering};
use std::collections::BTreeSet;

fn main() {
    dbg!(by_distance_from(-5));
}

fn by_distance_from(x: i32) -> Vec<i32> {
    let v = vec![-5, 0, 1, 3, 10];
    struct Comp<'a> {
        cmp: &'a Cmp,
        v: i32,
    }
    struct Cmp {
        x: i32,
    }
    let cmp = Cmp { x };
    impl PartialOrd for Comp<'_> {
        fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
            self.v.abs_diff(self.cmp.x).partial_cmp(&other.v.abs_diff(other.cmp.x))
        }
    }
    impl Ord for Comp<'_> {
        fn cmp(&self, other: &Self) -> Ordering {
            self.partial_cmp(other).unwrap()
        }
    }
    impl PartialEq for Comp<'_> {
        fn eq(&self, other: &Self) -> bool {
            self.v == other.v
        }
    }
    impl Eq for Comp<'_> {}
    let s: BTreeSet<_> = v.into_iter().map(|v| Comp {
        cmp: &cmp,
        v,
    }).collect();
    s.into_iter().map(|Comp { v, ..}| v).collect()
}

Playground

相关问题