rust 如何从匹配表达式返回值而不在函数中返回?

5vf7fwbs  于 2023-10-20  发布在  其他
关注(0)|答案(2)|浏览(109)

所以我是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循环超过两次。我怀疑这是因为循环内部的返回,我认为Rust认为这是函数的返回,而不是为current_mode赋值的返回。
我如何重写下面的代码来实际为current_mode赋值,而不仅仅是返回?

uidvcgyl

uidvcgyl1#

你的怀疑是正确的,你只能从函数返回,而不是像循环和匹配语句这样的控制流结构。所以它总是从整个函数返回而不继续。
如果你想利用提前返回,你可以将函数分成两个,在Some(mode)的情况下使用一个助手,并在主get_mode_of函数中调用它。
然而,在这种情况下,你应该能够利用Rust的块表达式计算到它们的最后一个部分或操作数(资源:https://doc.rust-lang.org/reference/expressions/block-expr.html)像这样:

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

g6baxovj2#

作为替代方案,这是一个XY问题,因为标准库有Iterator::max_by(),它允许您通过自定义比较函数将值序列减少到最大值。因此,在代码中写出这种逻辑对于标准库来说是多余的;使用Iterator实用程序即可。
你也不需要通过可变引用来获取Map,因为你没有改变它。一个不可变的引用就可以了。
举例来说:

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))
}

相关问题