使用多个键排序时反转特定键

时间:2016-11-01 21:54:34

标签: sorting rust

使用多个键排序时,如何反转单个键的顺序?例如:

vec.sort_by_key(|k| (foo(k).reverse(), bar(k)));

3 个答案:

答案 0 :(得分:6)

您可以使用与sort_by配对的Ordering::reverse代替sort_by_key

use std::cmp::Ordering;

#[derive(Debug)]
struct Foo(&'static str, u8);

impl Foo {
    fn name(&self) -> &str { self.0 }
    fn len(&self) -> u8 { self.1 }
}

fn main() {
    let mut vec = vec![Foo("alpha", 1), Foo("beta", 2), Foo("beta", 1)];

    vec.sort_by(|a, b| {
        match a.name().cmp(b.name()).reverse() {
            Ordering::Equal => a.len().cmp(&b.len()),
            other => other,
        }
    });

    println!("{:?}", vec);
}

按反向字母顺序排序,然后按升序排列关系:

[Foo("beta", 1), Foo("beta", 2), Foo("alpha", 1)]

自Rust 1.17(通过RFC 1677)以来,您可以这样写:

vec.sort_by(|a, b| {
    a.name().cmp(b.name()).reverse()
        .then(a.len().cmp(&b.len()))
});

如果你有自然可以否定/倒置的东西,你可以simply negate the key

答案 1 :(得分:4)

revord crate(documentation)提供了一个结构RevOrd,它通过调用{{1}来包装值并实现PartialOrdOrd }和partial_cmp使用交换参数以返回反转顺序。只需将密钥包装在cmp结构中按降序排序。

RevOrd

自Rust 1.19起,std::cmp::Reverse结构提供了相同的好处:

vec.sort_by_key(|k| (RevOrd(foo(k)), bar(k)));

答案 2 :(得分:2)

这是解决问题的类似方法:创建链接多个排序的函数:

/// chain two orderings: the first one gets more priority
fn chain_ordering(o1: Ordering, o2: Ordering) -> Ordering {
    match o1 {
        Ordering::Equal => o2,
        _ => o1,
    }
}

然后使用sort_by(可能带有模式匹配)来生成每个键的顺序:

#[derive(Debug, PartialEq)]
struct HeroSkill(&'static str, &'static str);

fn main() {
    // a vector of hero names and super powers
    let mut v = vec![
        HeroSkill("Bob", "X"),
        HeroSkill("Bob", "Y"),
        HeroSkill("Alice", "X")
    ];

    // sort by name, then by super power, where Y is more powerful than X
    v.sort_by(|&HeroSkill(name1, power1), &HeroSkill(name2, power2)| {
        chain_ordering(name1.cmp(name2), power1.cmp(power2).reverse())
    });

    assert_eq!(v, vec![
        HeroSkill("Alice", "X"),
        HeroSkill("Bob", "Y"),
        HeroSkill("Bob", "X")
    ]);
}

Playground