如何用1以外的步骤迭代Rust中的某个范围?我来自C ++背景,所以我想做些类似的事情
for(auto i = 0; i <= n; i+=2) {
//...
}
在Rust中,我需要使用该range
函数,而且似乎没有第三个参数可用于执行自定义步骤。我该怎么做?
Answers:
range_step_inclusive
并且range_step
早已不复存在。
从Rust 1.28开始,它Iterator::step_by
是稳定的:
fn main() {
for x in (1..10).step_by(2) {
println!("{}", x);
}
}
在我看来,在.step_by
方法变得稳定之前,您可以轻松地通过使用Iterator
(这Range
实际上是真正的)完成您想要的事情:
struct SimpleStepRange(isize, isize, isize); // start, end, and step
impl Iterator for SimpleStepRange {
type Item = isize;
#[inline]
fn next(&mut self) -> Option<isize> {
if self.0 < self.1 {
let v = self.0;
self.0 = v + self.2;
Some(v)
} else {
None
}
}
}
fn main() {
for i in SimpleStepRange(0, 10, 2) {
println!("{}", i);
}
}
如果需要迭代多个不同类型的范围,则可以使代码通用,如下所示:
use std::ops::Add;
struct StepRange<T>(T, T, T)
where for<'a> &'a T: Add<&'a T, Output = T>,
T: PartialOrd,
T: Clone;
impl<T> Iterator for StepRange<T>
where for<'a> &'a T: Add<&'a T, Output = T>,
T: PartialOrd,
T: Clone
{
type Item = T;
#[inline]
fn next(&mut self) -> Option<T> {
if self.0 < self.1 {
let v = self.0.clone();
self.0 = &v + &self.2;
Some(v)
} else {
None
}
}
}
fn main() {
for i in StepRange(0u64, 10u64, 2u64) {
println!("{}", i);
}
}
如果需要无限循环,我将留给您消除上限检查以创建开放式结构...
这种方法的优点是可以for
加糖,即使不稳定的功能可用也可以继续使用。而且,与使用标准Range
s的消减方法不同,它不会因多次.next()
调用而失去效率。缺点是设置迭代器需要花费几行代码,因此仅对于具有很多循环的代码才值得。
U
您可以在第二个选项中使用支持其他类型加法的类型,但仍会产生a T
。例如,时间和持续时间浮现在脑海。
将数字箱与range_step一起使用
您将编写C ++代码:
for (auto i = 0; i <= n; i += 2) {
//...
}
...在Rust中是这样的:
let mut i = 0;
while i <= n {
// ...
i += 2;
}
我认为Rust版本也更具可读性。
continue
,以使其正常工作。尽管可以做到,但这种设计会鼓励错误。
如果您要逐步执行一些预定义的操作(例如2),则可能希望使用迭代器手动执行操作。例如:
let mut iter = 1..10;
loop {
match iter.next() {
Some(x) => {
println!("{}", x);
},
None => break,
}
iter.next();
}
您甚至可以用它随意增加一个步长(尽管这肯定会变得越来越长且更难消化):
let mut iter = 1..10;
let step = 4;
loop {
match iter.next() {
Some(x) => {
println!("{}", x);
},
None => break,
}
for _ in 0..step-1 {
iter.next();
}
}