我有Vector名球员要根据以下标准进行排序:

  1. 乘以championships(降序)
  2. 乘以wins(降序)
  3. 乘以name(升序)

我在Rust中实现了如下内容:

use std::cmp::Ordering;

#[derive(Debug)]
struct Player {
    name: String,
    championships: u8,
    wins: u8,
}

fn main() {
    let mut players = vec![
        Player {
            name: "Alice".to_string(),
            championships: 3,
            wins: 17,
        },
        Player {
            name: "Bob".to_string(),
            championships: 3,
            wins: 19,
        },
        Player {
            name: "Claire".to_string(),
            championships: 4,
            wins: 18,
        },
        Player {
            name: "Dan".to_string(),
            championships: 4,
            wins: 18,
        },
    ];
    players.sort_by(|a, b| match b.championships.cmp(&a.championships) {
        Ordering::Less => Ordering::Less,
        Ordering::Greater => Ordering::Greater,
        Ordering::Equal => match b.wins.cmp(&a.wins) {
            Ordering::Less => Ordering::Less,
            Ordering::Greater => Ordering::Greater,
            Ordering::Equal => match a.name.cmp(&b.name) {
                Ordering::Less => Ordering::Less,
                Ordering::Greater => Ordering::Greater,
                Ordering::Equal => Ordering::Equal,
            },
        },
    });
    dbg!(players);
}

如输出所示,这可以按预期工作:

[src/main.rs:46] players = [
    Player {
        name: "Claire",
        championships: 4,
        wins: 18,
    },
    Player {
        name: "Dan",
        championships: 4,
        wins: 18,
    },
    Player {
        name: "Bob",
        championships: 3,
        wins: 19,
    },
    Player {
        name: "Alice",
        championships: 3,
        wins: 17,
    },
]

然而,模式匹配代码非常重复,因为在大多数情况下,我只返回已有的代码,例如:

Ordering::Less => Ordering::Less,
Ordering::Greater => Ordering::Greater,

有什么捷径可以避免这种冗长的话吗?

这不是一个真正的排序问题,而是一个模式匹配问题.(也许按多个标准进行排序可以用一种更优雅的方式进行,我不知道该怎么做,因为我有升序/降序的排序标准.)

推荐答案

链接您的示例中的比较是std::cmp::Ordering::then(和then_with)的作用:

players.sort_by(|a, b| {
    b.championships
        .cmp(&a.championships)
        .then(b.wins.cmp(&a.wins))
        .then(b.name.cmp(&a.name).reverse())
});

Rust相关问答推荐

捕获Rust因C++异常而产生panic

泛型属性比较

是否有可能同时避免不兼容的不透明类型和代码重复?

何时可以在Rust中退出异步操作?

铁 rust 干线无法使用PowerShell获取环境变量

下载压缩文件

在自定义序列化程序中复制serde(With)的行为

替换可变引用中的字符串会泄漏内存吗?

我可以在不收集或克隆的情况下,将一个带有Item=(key,val)的迭代器拆分成单独的key iter和val iter吗?

`Pin`有没有不涉及不安全代码的目的?

rust中的库插件管理器,现在是否可行?

sha256 摘要仅适用于 &*

注释闭包参数强调使用高阶排定特征界限

`tokio::pin` 如何改变变量的类型?

从光标位置旋转精灵

实现泛型的 Trait 方法中的文字

如何将这些测试放在一个单独的文件中?

为什么数组不像向量那样在 for 块之后移动?

为什么 &i32 可以与 Rust 中的 &&i32 进行比较?

tokio async rust 的 yield 是什么意思?