Rustの範囲を1以外のステップで反復するにはどうすればよいですか?私はC ++のバックグラウンドから来ているので、次のようなことをしたいと思います。
for(auto i = 0; i <= n; i+=2) {
//...
}
Rustではrange
関数を使用する必要がありますが、カスタムステップを使用するために使用できる3番目の引数がないようです。どうすればこれを達成できますか?
回答:
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
、2番目のオプションに、別の型での追加をサポートする型を使用しても、を生成できT
ます。たとえば、時間と期間が思い浮かびます。
使用num個でクレートをrange_step
あなたはあなたのC ++コードを書くでしょう:
for (auto i = 0; i <= n; i += 2) {
//...
}
...そのような錆で:
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();
}
}