在 Rust 中为 Option<number> 做 max 的惯用方法

Geo*_*lin 3 optional rust

我有一个号码Option。我需要用它的最大值和其他一些值来替换它,或者如果我的号码是None.

我写了一个函数来这样做:

fn max(a: Option<u32>, b: u32) -> Option<u32> {
    if a.is_some() {
        Some(std::cmp::max(a.unwrap(), b))
    } else {
        Some(b)
    }
}
Run Code Online (Sandbox Code Playgroud)

但我不能停止认为有一种更好、更简洁的方法可以使用Option. 你能帮助我吗?

Öme*_*den 8

最大限度:

Option<T> Implements OrdTImplements时Ord,因此可以像这样实现您的函数:

fn max(a: Option<u32>, b: u32) -> Option<u32> {
    std::cmp::max(a, Some(b))
}
Run Code Online (Sandbox Code Playgroud)

操场


请注意:

对于每个T: Ord, Some<T> 都大于None, 满足您的要求。

这没有记录,但我们可以证明:

由于Ord类型形成全序。这意味着它们需要具有传递性;ifNone小于Some(MIN)thenNone将小于 set( Option<T>) 中的任何其他值,因为Some(MIN)小于该集合中的任何值,除了None

assert!(Some(std::i64::MIN) > None);
Run Code Online (Sandbox Code Playgroud)

分钟:

您还可以std::cmp::min通过添加额外的 来扩展or,这也适用于这种max情况,但不需要,因为将进行额外的检查和与 的b解决方案进行比较的值的额外副本max

fn min(a: Option<u32>, b: u32) -> Option<u32> {
    std::cmp::min(a.or(Some(b)), Some(b))
}
Run Code Online (Sandbox Code Playgroud)

操场

  • @GeorgeShuklin 谢谢,我已经为“min”添加了替代解决方案,希望它有帮助。 (3认同)

Net*_*ave 5

使用map

fn max(a: Option<u32>, b: u32) -> Option<u32> {
    a.map(|v| std::cmp::max(v, b))
}
Run Code Online (Sandbox Code Playgroud)

操场

或者map_or默认未包装的术语:

fn max(a: Option<u32>, b: u32) -> Option<u32> {
    a.map_or(Some(b), |v| Some(std::cmp::max(v, b)))
}

Run Code Online (Sandbox Code Playgroud)

操场

对于您实际上不需要返回的Option:

fn max(a: Option<u32>, b: u32) -> u32 {
    a.map_or(b, |v| std::cmp::max(v, b))
}

Run Code Online (Sandbox Code Playgroud)