ユーニックス総合研究所

  • home
  • archives
  • rust-iter

Rustのイテレータ(iter)の使い方

  • 作成日: 2022-07-03
  • 更新日: 2023-12-25
  • カテゴリ: Rust

Rustのイテレータの使い方

Rustにはイテレータがあります。
これはiter()で作れます。

ベクターなどをfor文で回したい時にイテレータは使うことができます。
この記事ではRustのイテレータについて解説します。

イテレータの使い方を覚えておけばそこから派生するいろいろな処理も行うことができます。
大量のデータを処理したい時はイテレータが必須になってきます。

関連記事

文字列の描画 - Rustで作るWindowsアプリ
改行付きの文字列を描画する - Rustで作るWindowsアプリ
ラベルの表示 - Rustで作るWindowsアプリ
ラベルの色を変える - Rustで作るWindowsアプリ
ライセンス表示 - Rustで作るWindowsアプリ

iter()でイテレータを作る

ベクター(Vec)のメソッドにiter()があります。
これを呼び出すとそのベクターのイテレータを作ることができます。

let v = vec![1, 2, 3];  
let it = v.iter();  

println!("{:?}", it);  
// Iter([1, 2, 3])  

イテレータ自体はIteratorというトレイトを使って実装されています。
このトレイトにはnext()などのメソッドが定義されています。

pub trait Iterator {  
    type Item;  

    fn next(&mut self) -> Option<Self::Item>;  

    // ...  
    // 他にもメソッドたくさん  
}  

Rustではイテレータを作ってメソッドを呼び出し計算処理を行うということが多く行われます。
そのためiter()はそういった処理の入り口になるメソッドと言えます。

イテレータをfor文で回す

イテレータをfor文に渡すと各要素を取り出すことができます。
↓はベクターをイテレータを使ってfor文で回しているところです。

let v = vec![1, 2, 3];  

for el in v.iter() {  
    println!("{}", el);  
}  
// 1  
// 2  
// 3  

取り出される要素は先頭からになります。

rev()でリバースする

iter().rev()をすると走査方向を反転させることができます。
ベクターの末尾から要素を回したい時などに使います。

let v = vec![1, 2, 3];  

for el in v.iter().rev() {  
    println!("{}", el);  
}  
// 3  
// 2  
// 1  

next()でイテレータを進める

next()はイテレータの内部状態を1つ進めるメソッドです。
next()を呼び出すとイテレータが進みます。

next()Option<Self::Item>を返してきます。
値を取り出したい場合はunwrap()します。

let v = vec![1, 2, 3];  
let mut it = v.iter();  

println!("{}", it.next().unwrap());  // 1  
println!("{}", it.next().unwrap());  // 2  
println!("{}", it.next().unwrap());  // 3  

count()で要素をカウントする

ベクターなどの要素数を得たい場合はcount()を使います。
↓は要素数が3のベクターを定義しています。
そしてv.iter().count()で要素数をカウントします。

let v = vec![1, 2, 3];  

println!("{}", v.iter().count());  // 3  

filter()で要素をフィルタリング

filter()は各要素を1つずつ見ていって条件に合う要素を抽出するメソッドです。
[1, 2, 3, 4]というベクターから偶数のベクターのみを抽出します。
fitler()にはラムダ式を渡します。この式が条件になります。
|&x| x % 2 == 0という式にすると要素が偶数の場合にその要素を結果に格納します。

イテレータをベクターに変換したい場合はcloned()してcollect()します。
↓のresultがそうです。
resultVec<i32>という型にしてあります。
これは走査しているベクターがi32のベクターだからです。

let v = vec![1, 2, 3, 4];  
let result: Vec<i32> = v.iter().filter(|&x| x % 2 == 0).cloned().collect();  

println!("{:?}", result);  // [2, 4]  

map()で要素をすべて処理

map()は各要素を1つずつ見ていってその要素を新たな結果として格納します。
たとえば整数のベクターがあってそのベクター内の各要素をすべて倍にして、それを新しいベクターにしたいとします。
そういう時は↓のようにします。

map()は引数としてラムダ式を取ります。
ラムダ式を|&x| x * 2にすると要素の値が倍になります。

let v = vec![1, 2, 3];  
let result: Vec<i32> = v.iter().map(|&x| x * 2).collect();  

println!("{:?}", result);  // [2, 4, 6]  

sum()で各要素の合計を得る

sum()は各要素の合計値を取るメソッドです。
↓のようにベクターのイテレータから呼び出すとベクターの各要素の合計値が得られます。

let v = vec![1, 2, 3];  
let sum: i32 = v.iter().sum();  

println!("{}", sum);  // 6  

おわりに

今回はRustのイテレータについて解説しました。
Rustではイテレータを使う機会が多いです。
覚えておくとプログラミングが捗ります。

🦝 < レッツ・イテレータ

🐭 < 要素を取り出すぞ