当向量
0 .. v.len() - 1
可能为空时,处理 v
的正确方法是什么?
考虑以下代码,它打印向量中 2 个元素的所有选择
[5, 6, 7]
:
fn main() {
let v: Vec<i32> = vec![5, 6, 7];
for i in 0 .. v.len() - 1 {
for j in i + 1 .. v.len() {
println!("{} {}", v[i], v[j]);
}
}
}
打印出来了
5 6
5 7
6 7
正如预期的那样。
现在,如果我们有
let v: Vec<i32> = vec![];
然后程序会因为溢出而恐慌,这也在意料之中。
问:如何在不改变程序结构和逻辑、不涉及有符号整数的情况下修复它?
以下是我不想要的解决方法的一些示例:
v
(改变逻辑)。总的来说,我不想检查 v
是否为空,例如通过 if v.len() == 0 { 0 } else { v.len() - 1 }
for j in 0 .. v.len() {
for i in 0 .. j {
for i in 1 .. v.len() {
for j in i .. v.len() {
// Now i is shifted by 1
for i in 0 .. v.len() as i32 - 1 {
for j in i + 1 .. v.len() as i32 {
// cast i and j to usize
总的来说,我希望有一种干净的方法来处理
0 .. v.len() - 1
,而不需要任何黑客攻击。
为了解决当向量
0 .. v.len() - 1
可能为空时处理 v
的问题,我们可以使用 Rust 的 checked_sub
方法从向量的长度中安全地减一,而不会有整数下溢的风险。如果减法会导致下溢,则此方法返回 Option
,即 None
,否则返回结果 Some
。
以下是如何在代码中实现它:
fn main() {
let v: Vec<i32> = vec![5, 6, 7];
if let Some(max_index) = v.len().checked_sub(1) {
for i in 0..max_index {
for j in i + 1..v.len() {
println!("{} {}", v[i], v[j]);
}
}
}
// If v is empty, the loop will not execute, avoiding the panic.
}
即使向量
v
为空,此代码也能正常工作,因为 checked_sub(1)
将返回 None
并且循环不会执行。该方案不会改变程序的结构或逻辑,不涉及有符号整数,也不需要单独处理空向量情况。
经过更多谷歌搜索后,我发现了saturating_sub。