如何在函数中不使用 returning 的情况下 return 来自匹配表达式的值?

How to return a value from a match expression without returning in the function?

所以我是 Rust 的新手,所以修复起来可能真的很微不足道。我一直在关注我的 Rust 安装随附的编程书籍,到目前为止一切顺利。我在第 8.3 章,最后第一个练习是实现一个函数,该函数将获取值列表的中值和众数。计算模式的功能无法正常工作。

这是我当前的实现:

fn get_mode_of(number_count: &mut HashMap<i32, u32>) -> Option<(i32, u32)> {
    let mut current_mode: Option<(i32, u32)> = None;
    for (number, count) in number_count {
        println!("Comparing: ({}, {})", number, count);
        current_mode = match current_mode {
            None => Some((*number, *count)),
            Some(mode) => {
                if let Ordering::Less = mode.1.cmp(&count) {
                    println!("Comparing value: {} and {}", mode.1, count);
                    return Some((*number,*count));
                }
                println!("Comparing value: {} and {}", mode.1, count);
                return Some(mode);
            }
        };
        println!("Current mode is None: {}", {current_mode.is_none()});
    }
    return current_mode;
}

问题是,程序不会运行 for 循环超过两次。我怀疑这是因为循环内的 returns,我认为 Rust 认为这是函数的 return 而不是 return 来为 current_mode 赋值.

我如何重写下面的代码以实际为 current_mode 赋值,而不仅仅是 returning?

您的怀疑是正确的,您只能 return 来自函数而不是循环和匹配语句等控制流结构。所以它总是从整个函数中 return 而不会继续。

如果您想利用早期的 returns,您可以使用 Some(mode) 案例的帮助程序将函数分成两个,并在主 get_mode_of 函数中调用它.

但是,在这种情况下,您应该能够利用 Rust 的块表达式计算其最后一部分或操作数(资源:https://doc.rust-lang.org/reference/expressions/block-expr.html),如下所示:

Some(mode) => {
    if let Ordering::Less = mode.1.cmp(&count) {
        println!("Comparing value: {} and {}", mode.1, count);
        Some((*number,*count))
    } else {
        println!("Comparing value: {} and {}", mode.1, count);
        Some(mode)
    }
}

作为替代方案,这是一个 XY 问题,因为标准库有 Iterator::max_by(),它允许您通过自定义比较函数将一系列值减少到最大值。因此,在你的代码中写出这个逻辑对于标准库来说是多余的;只需使用 Iterator 实用程序即可。

您也不需要通过可变引用获取地图,因为您不需要更改它。一个不可变的引用就可以了。

例如:

fn get_mode_of(number_count: &HashMap<i32, u32>) -> Option<(i32, u32)> {
    number_count.iter()
        .max_by(|a, b| a.1.cmp(b.1))
        // Here we have Option<(&i32, &u32)>, map that to Option<(i32, u32)>
        .map(|(&a, &b)| (a, b))
}