如何在函数中不使用 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))
}
所以我是 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))
}