Rust 在 "None" 上跳过循环,否则继续计算
Rust skip loop on "None" else move forward with computation
我有一个嵌套循环,我想在其中检查某个条件是否适用于 table 的 usize
值。然而,table 可能只被部分填充——所以它实际上是 table 个 Option<usize>
变量。当至少有一个值缺失时,我认为不违反条件,因此想继续使用下一组值。
目前我是这样操作的:
for i in 0..n {
for j in 0..n {
for k in 0..n {
let v_ij = match table[i][j] {
None => { continue; },
Some(val) => { val }
};
let v_jk = match table[j][k] {
None => { continue; },
Some(val) => { val }
};
let res_left = match table[v_ij][k] {
None => { continue; },
Some(val) => { val }
};
let res_right = match table[i][v_jk] {
None => { continue; },
Some(val) => { val }
};
if res_left != res_right {
return false;
}
}
}
}
(上下文:计算是检查部分岩浆是否结合,但这对问题并不重要。)
是否有一种惯用的方法来替换所有这些匹配项?在 Haskell 中,使用 Maybe monad,我相信我可以将这段代码包装到 do
块中,以便自动传播 None
值。我尝试使用 table[i][j].unwrap_or({continue;})
但这会贪婪地评估 continue
;使用 table[i][j].unwrap_or_else({continue;})
会出现语法错误。
在这种情况下,为了限制重复并提高清晰度,我可能会使用宏:
macro_rules! unwrap_or_continue {
($opt: expr) => {
match $opt {
Some(v) => v,
None => {continue;}
}
}
}
有 loop_unwrap 个 crate 实现了类似但更复杂的东西。
这样你的每一个测试都会减少:
for i in 0..n {
for j in 0..n {
for k in 0..n {
let v_ij = unwrap_or_continue!(table[i][j]);
let v_jk = unwrap_or_continue!(table[j][k]);
let res_left = unwrap_or_continue!(table[v_ij][k]);
let res_right = unwrap_or_continue!(table[i][v_jk]);
if res_left != res_right {
return false;
}
}
}
}
在选项上使用 ?
运算符为您执行 continue
,并使用 itertools 构建迭代器,您可以采用函数式方法:
use itertools::Itertools;
let has_false = (0..n)
.permutations(3)
.filter_map(|v| {
let (i, j, k) = (v[0], v[1], v[2]);
let v_ij = table[i][j]?;
let v_jk = table[j][k]?;
Some((table[v_ij][k]?, table[i][v_jk]?))
})
.any(|(res_left, res_right)| res_left != res_right);
我有一个嵌套循环,我想在其中检查某个条件是否适用于 table 的 usize
值。然而,table 可能只被部分填充——所以它实际上是 table 个 Option<usize>
变量。当至少有一个值缺失时,我认为不违反条件,因此想继续使用下一组值。
目前我是这样操作的:
for i in 0..n {
for j in 0..n {
for k in 0..n {
let v_ij = match table[i][j] {
None => { continue; },
Some(val) => { val }
};
let v_jk = match table[j][k] {
None => { continue; },
Some(val) => { val }
};
let res_left = match table[v_ij][k] {
None => { continue; },
Some(val) => { val }
};
let res_right = match table[i][v_jk] {
None => { continue; },
Some(val) => { val }
};
if res_left != res_right {
return false;
}
}
}
}
(上下文:计算是检查部分岩浆是否结合,但这对问题并不重要。)
是否有一种惯用的方法来替换所有这些匹配项?在 Haskell 中,使用 Maybe monad,我相信我可以将这段代码包装到 do
块中,以便自动传播 None
值。我尝试使用 table[i][j].unwrap_or({continue;})
但这会贪婪地评估 continue
;使用 table[i][j].unwrap_or_else({continue;})
会出现语法错误。
在这种情况下,为了限制重复并提高清晰度,我可能会使用宏:
macro_rules! unwrap_or_continue {
($opt: expr) => {
match $opt {
Some(v) => v,
None => {continue;}
}
}
}
有 loop_unwrap 个 crate 实现了类似但更复杂的东西。
这样你的每一个测试都会减少:
for i in 0..n {
for j in 0..n {
for k in 0..n {
let v_ij = unwrap_or_continue!(table[i][j]);
let v_jk = unwrap_or_continue!(table[j][k]);
let res_left = unwrap_or_continue!(table[v_ij][k]);
let res_right = unwrap_or_continue!(table[i][v_jk]);
if res_left != res_right {
return false;
}
}
}
}
在选项上使用 ?
运算符为您执行 continue
,并使用 itertools 构建迭代器,您可以采用函数式方法:
use itertools::Itertools;
let has_false = (0..n)
.permutations(3)
.filter_map(|v| {
let (i, j, k) = (v[0], v[1], v[2]);
let v_ij = table[i][j]?;
let v_jk = table[j][k]?;
Some((table[v_ij][k]?, table[i][v_jk]?))
})
.any(|(res_left, res_right)| res_left != res_right);