【问题标题】:Skipping elements while iterating over a slice with a for loop [duplicate]在使用 for 循环遍历切片时跳过元素[重复]
【发布时间】:2020-04-07 12:15:44
【问题描述】:

在 Rust 中,如何在 for 样式循环中执行可变大小的步骤?我可以用这个结构做固定大小的步骤:

for i in (0..vals.len()).step_by(4)
{
    println!("{}: {}", i, vals[i]);
}

或更恰当的:

for (i,val) in vals.iter().enumerate().step_by(4)
{
    println!("{}: {}", i, val);
}

但我真正想做的是:

for i in 0..vals.len()
{
    println!("{}: {}", i, vals[i]);
    if      vals[i] == 1 { i += 2; }
    else if vals[i] == 2 { i += 4; }
}

当然,修改i 不会影响循环迭代器。

主要来自 C 背景,在现代语言中对迭代器的依赖通常感觉就像戴着手套进行编程一样。通常谷歌会来救援,但我还没有找到任何解决方案来解决这个看似相当简单的问题。

我想出的最好的是

let mut i:usize = 0;
while i < vals.len()
{
    println!("{}: {}", i, vals[i]);
    if      vals[i] == 1  { i += 2; }
    else if vals[i] == 2  { i += 4; }
}

但这感觉就像一个穷人的for 循环,与我应该做的事情相反,以利用配备迭代器的语言。是否有continue 的变体可以跳过迭代,或者有一种方法可以从循环内的迭代器上调用skip

【问题讨论】:

  • 我实际上并不认为这是重复的,因为另一个问题的迭代器是一个“真正的”迭代器——除了调用 next() 两次之外,没有办法跳过 2 个项目。这种情况比较窄,卢卡斯的回答是这个问题的好答案,但不适用于另一个。

标签: for-loop rust iterator


【解决方案1】:

真的没有更好的选择。我仍然可以想到这个:

let mut skip = 0;
for (i, val) in vals.iter().enumerate() {
    if skip > 0 {
        skip -= 1;
        continue;
    }

    println!("{}: {}", i, val);

    skip = match val {
        1 => 2,
        2 => 4,
        _ => 0,
    };
}

但这并不一定比你已有的想法更好。

没有“好的”解决方案的原因仅仅是因为这种用例非常罕见。 for 循环用于完全迭代迭代器的常见情况。对于需要一些更复杂的“高级迭代器”逻辑的情况,whileloop 循环可以满足您的需求。这些循环并不“坏”,它们正是针对这种情况的。

我认为您的while 循环解决方案非常好!

【讨论】:

  • 在循环范围之外保留一个可变的跳过计数器也是我下一个最丑陋的解决方案!非常感谢这个答案,感谢“for 循环适用于常见情况......” - 帮助调整了我对for 循环的期望,并认为它与(有限且强大的)迭代器世界交织在一起。执行功能性计算机科学任务对我来说是最不常见的情况,副作用通常是我的目标,所以这有助于调整我的目标。
猜你喜欢
  • 2021-07-31
  • 2013-04-20
  • 2016-01-26
  • 2021-06-16
  • 2023-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-18
相关资源
最近更新 更多