LoginSignup
1
2

More than 1 year has passed since last update.

Rust 研究:イテレータ

Last updated at Posted at 2023-04-01

Rust のイテレータの勉強をしました。

練習がてらフィボナッチ数列を生成するイテレータを実装してみましたのでメモを残します。

フィボナッチ数列

イテレータの前にフィボナッチ数列のおさらいです。

次の漸化式であらわされます。

F(0) => 1
F(1) => 1
F(n) => F(n-2) + F(n-1) (n > 1)

1, 1, 2, 3, 5, 8, 13, 21, ... と無限に続きます。

思わず再帰的な実装をしたくなりますが、イテレーションの練習なので、ここは我慢してループを使ったあまり面白くない実装をします。

// fib は上限値を超えないフィボナッチ数列を表示する
pub fn fib (upper_limit:usize) {

    let mut a:usize = 0;
    let mut b:usize = 1;

    while b <= upper_limit {
        (a, b) = (b, a + b);
        print!("{} ", a);
    }
}

関数 fib は引数で与えられた「上限値」を超えないフィボナッチ数列を表示します。

// 100 を超えないフィボナッチ数列の表示
fib(100);

// 実行結果
1 1 2 3 5 8 13 21 34 55 89

イテレータでの実装

さきほどの fib 関数の実装に準じて、a / b / upper_limit のメンバ変数をもつ構造体とコンストラクタを用意します。

pub struct Fib {
    a: usize,
    b: usize,
    upper_limit: usize,
}

impl Fib {
    pub fn till(upper_limit:usize) -> Self {
        Fib {
            a: 0,
            b: 1,
            upper_limit: upper_limit,
        }
    }
}

続いて Iterator トレイトの next メソッドの実装です。

impl Iterator for Fib {
    type Item = usize;
    
    fn next (&mut self) -> Option<Self::Item> {
        // 上限値を超える場合は None を返す
        if self.b > self.upper_limit {
            return None
        }

        // 次のフィボナッチ数を計算
        (self.a, self.b) = (self.b, self.a + self.b);

        Some(self.a)
    }
}

上限値を超える場合は None を返してイテレーションの終わりをおしえます。

実行例です。

// for で各数を表示
for n in Fib::till(100) {
    print!("{} ", n);
}

// 実行結果
1 1 2 3 5 8 13 21 34 55 89

イテレータにすると処理のバリエーションが広がります。

  • for_each で各数を表示
Fib::till(100).for_each(|x|print!("{} ", x));

// 実行結果
1 1 2 3 5 8 13 21 34 55 89
  • collect でベクタ化
let fs:Vec<usize> = Fib::till(100).collect();
println!("{:?}", fs);

// 実行結果
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
  • map で各数を変換し、collect でベクタ化
let fs:Vec<String> = Fib::till(100).map(|x|format!("{}", x)).collect();
println!("{}", fs.join(" "));

// 実行結果
1 1 2 3 5 8 13 21 34 55 89
  • eumerate で各数のインデクスを付与
Fib::till(100).enumerate().for_each(|(i, x)|println!("F({})=>{}", i, x));

// 実行結果
F(0)=>1
F(1)=>1
F(2)=>2
F(3)=>3
F(4)=>5
F(5)=>8
F(6)=>13
F(7)=>21
F(8)=>34
F(9)=>55
F(10)=>89
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2