MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
Rustの基礎 - 反復処理(for文)のソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
Rustの基礎 - 反復処理(for文)
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == Rustにおいて、反復処理 (イテレーション) をするfor文、および、範囲(Range)とイテレータを使用した処理を記載する。<br> <br> Rustのfor文は、イテレータを実装した型 (配列、ベクタ、範囲等) に対して反復処理を行う。<br> Rustのfor文は、他の言語と異なり、常にイテレータパターンを使用する。<br> <br><br> == for-in文で反復処理をする == for文を使用してループ処理を記述する場合は、forの後ろに繰り返し変数を記述する。<br> 続けて、<code>in</code> キーワードを記述した後にイテラブルなオブジェクトを記述して、波括弧{}でブロックを囲む。<br> <syntaxhighlight lang="rust"> for 繰り返し変数 in イテラブルなオブジェクト { 実行コード } </syntaxhighlight> <br> 以下の例では、配列から各要素を取得している。<br> <syntaxhighlight lang="rust"> fn main() { let lang = ["Rust", "C++", "Go"]; for i in lang { println!("{}", i); } } // 出力 Rust C++ Go </syntaxhighlight> <br> ベクタ (vec) を使用する場合は、参照を使用する、または、<code>iter</code> メソッドを使用する。<br> <syntaxhighlight lang="rust"> fn main() { let lang = vec!["Rust", "C++", "Go"]; for i in &lang { println!("{}", i); } } // 出力 Rust C++ Go </syntaxhighlight> <br> 次に、文字列の各文字を反復処理する。<br> <code>chars</code> メソッドを使用して、文字列を文字単位で反復処理する。<br> <syntaxhighlight lang="rust"> fn main() { for s in "Rust".chars() { println!("{}", s); } } // 出力 R u s t </syntaxhighlight> <br><br> == break文でfor文を抜ける == break文を使用して反復処理を抜けることができる。<br> 以下の例では、取得した文字が's'の時にfor文から抜ける処理をしている。<br> <syntaxhighlight lang="rust"> fn main() { for s in "Rust".chars() { if s == 's' { break; } println!("{}", s); } } // 出力 R u </syntaxhighlight> <br> ラベル付きループを使用すると、入れ子になったループから外側のループを抜けることができる。<br> <syntaxhighlight lang="rust"> fn main() { 'outer: for i in 0..3 { for j in 0..3 { if i == 1 && j == 1 { break 'outer; } println!("i = {}, j = {}", i, j); } } } // 出力 i = 0, j = 0 i = 0, j = 1 i = 0, j = 2 i = 1, j = 0 </syntaxhighlight> <br><br> == continue文で処理をスキップする == continue文を使用して、処理をスキップして次の反復に進むことができる。<br> 以下の例では、指定した文字's'の場合のみ処理がスキップしている。<br> <syntaxhighlight lang="rust"> fn main() { for s in "Rust".chars() { if s == 's' { continue; } println!("{}", s); } } // 出力 R u t </syntaxhighlight> <br> ラベル付きループで、外側のループの次の反復に進むこともできる。<br> <syntaxhighlight lang="rust"> fn main() { 'outer: for i in 0..3 { for j in 0..3 { if j == 1 { continue 'outer; } println!("i = {}, j = {}", i, j); } } } // 出力 i = 0, j = 0 i = 1, j = 0 i = 2, j = 0 </syntaxhighlight> <br><br> == for文とHashMap (keys / values / iterメソッド) == HashMap型をfor文で処理する場合を考える。<br> <br> 次のようなHashMap型変数を用意して、for文で処理する。<br> HashMapをそのまま反復処理すると、キーと値のタプルが取得される。<br> <syntaxhighlight lang="rust"> use std::collections::HashMap; fn main() { let mut foods = HashMap::new(); foods.insert("breakfast", "miso soup"); foods.insert("lunch", "sandwich"); foods.insert("dinner", "steak"); for food in &foods { println!("{:?}", food); } } // 出力 ("breakfast", "miso soup") ("dinner", "steak") ("lunch", "sandwich") </syntaxhighlight> <br> <u>※注意</u><br> <u>HashMapは順序を保証しないため、出力順序は挿入順と異なる場合がある。</u><br> <br> ==== for文とHashMapのkeys()メソッド ==== HashMapのキーのみを反復処理する場合は、<code>keys</code> メソッドを使用する。<br> <syntaxhighlight lang="rust"> use std::collections::HashMap; fn main() { let mut foods = HashMap::new(); foods.insert("breakfast", "miso soup"); foods.insert("lunch", "sandwich"); foods.insert("dinner", "steak"); for food in foods.keys() { println!("{}", food); } } // 出力 breakfast dinner lunch </syntaxhighlight> <br> ==== for文とHashMapのvaluesメソッド ==== HashMapの値を反復処理で取得する場合は、<code>values</code> メソッドを使用する。<br> 以下の例では、valuesメソッドを使用してHashMapの値を取得している。<br> <syntaxhighlight lang="rust"> use std::collections::HashMap; fn main() { let mut foods = HashMap::new(); foods.insert("breakfast", "miso soup"); foods.insert("lunch", "sandwich"); foods.insert("dinner", "steak"); for food in foods.values() { println!("{}", food); } } // 出力 miso soup steak sandwich </syntaxhighlight> <br> ==== for文とHashMapのiterメソッド ==== HashMapのキーと値をセットで反復処理する場合は、<code>iter</code> メソッドを使用する。<br> <syntaxhighlight lang="rust"> use std::collections::HashMap; fn main() { let mut foods = HashMap::new(); foods.insert("breakfast", "miso soup"); foods.insert("lunch", "sandwich"); foods.insert("dinner", "steak"); for (key, value) in &foods { println!("({}, {})", key, value); } } // 出力 (breakfast, miso soup) (dinner, steak) (lunch, sandwich) </syntaxhighlight> <br> また、以下の例では、キーと値を使って文章を出力している。<br> <syntaxhighlight lang="rust"> use std::collections::HashMap; fn main() { let mut foods = HashMap::new(); foods.insert("breakfast", "miso soup"); foods.insert("lunch", "sandwich"); foods.insert("dinner", "steak"); for (food, menu) in &foods { println!("Yesterday, I had {} for {}.", menu, food); } } // 出力 Yesterday, I had miso soup for breakfast. Yesterday, I had steak for dinner. Yesterday, I had sandwich for lunch. </syntaxhighlight> <br><br> == 範囲 (Range) で反復処理 (数値のシーケンス生成) == for文において、範囲 (Range) が使用されることがよくある。<br> 範囲は、指定した範囲の数値を順に取得するイテラブルなオブジェクトである。<br> <br> 範囲の使用方法は、start..end (endは含まない)、または、start..=end (endを含む) という形で指定する。<br> <syntaxhighlight lang="rust"> fn main() { for i in 0..5 { println!("{}", i); } } // 出力 0 1 2 3 4 </syntaxhighlight> <br> 終了値を含む範囲を使用する場合は、..=演算子を使用する。<br> <syntaxhighlight lang="rust"> fn main() { for i in 0..=5 { println!("{}", i); } } // 出力 0 1 2 3 4 5 </syntaxhighlight> <br> <code>step</code> メソッド や <code>step_by</code> メソッドを使用して、一定の間隔で反復処理を行うことができる。<br> <syntaxhighlight lang="rust"> fn main() { for i in (1..10).step_by(3) { println!("{}", i); } } // 出力 1 4 7 </syntaxhighlight> <br> 範囲は、<code>collect</code> メソッドを使用してベクターに変換することができる。<br> <syntaxhighlight lang="rust"> fn main() { let a: Vec<i32> = (1..10).step_by(3).collect(); println!("{:?}", a); } // 出力 [1, 4, 7] </syntaxhighlight> <br> 逆順で反復処理を行う場合は、<code>rev</code> メソッドを使用する。<br> <syntaxhighlight lang="rust"> fn main() { for i in (0..5).rev() { println!("{}", i); } } // 出力 4 3 2 1 0 </syntaxhighlight> <br><br> == enumerateメソッドで反復処理 (インデックス付き反復処理) == <code>enumerate</code> メソッドを使用すると、インデックスと値のペアを取得できる。<br> <br> 以下の例では、配列を <code>enumerate</code> メソッドで処理し、インデックスと値を出力している。<br> <syntaxhighlight lang="rust"> fn main() { let lang = ["Rust", "C++", "Go"]; for (index, value) in lang.iter().enumerate() { println!("{}: {}", index, value); } } // 出力 0: Rust 1: C++ 2: Go </syntaxhighlight> <br> 開始インデックスを指定することもできる。<br> <syntaxhighlight lang="rust"> fn main() { let lang = ["Rust", "C++", "Go"]; for (index, value) in lang.iter().enumerate() { println!("{}: {}", index + 1, value); } } // 出力 1: Rust 2: C++ 3: Go </syntaxhighlight> <br><br> == zipメソッドで反復処理 (複数のイテレータの反復処理) == <code>zip</code> メソッドを使用すると、複数のイテレータを並列に反復処理することができる。<br> <br> 以下の例では、複数の配列をzip()メソッドでまとめて、それぞれの位置に対応した値を出力している。<br> 各配列の共通するインデックスの値が抜き出されて反復処理されている。<br> 要素数が異なる場合は、一番小さい要素数に合わせた回数で反復処理がなされる。 <syntaxhighlight lang="rust"> fn main() { let lang = ["Rust", "C++", "Go"]; let prefix = ["R", "C", "G"]; let suffix = ["t", "+", "o"]; for ((item1, item2), item3) in lang.iter().zip(prefix.iter()).zip(suffix.iter()) { println!("{} {} {}", item1, item2, item3); } } // 出力 Rust R t C++ C + Go G o </syntaxhighlight> <br> 3つ以上のイテレータをzip()する場合は、<code>izip!</code> マクロ (itertoolsクレート) を使用するとより簡潔に記述できる。<br> 標準ライブラリのみを使用する場合は、上記のようにzip()をネストさせる。<br> <br> 上記のサンプルコードを範囲とインデックスを使用して記述すると、以下のようになる。<br> 実行すると同様の結果が出力される。<br> <syntaxhighlight lang="rust"> fn main() { let lang = ["Rust", "C++", "Go"]; let prefix = ["R", "C", "G"]; let suffix = ["t", "+", "o"]; for i in 0..lang.len() { println!("{} {} {}", lang[i], prefix[i], suffix[i]); } } // 出力 Rust R t C++ C + Go G o </syntaxhighlight> <br><br> == イテレータメソッドチェーンによる高度な反復処理 == Rustのイテレータは、<code>map</code>、<code>filter</code>、<code>fold</code> メソッド等のメソッドをチェーンすることで、強力な反復処理を記述できる。<br> <br> ==== mapメソッドで要素を変換する ==== <code>map</code> メソッドは、各要素に対して関数を適用して新しいイテレータを生成する。<br> <syntaxhighlight lang="rust"> fn main() { let numbers = vec![1, 2, 3, 4, 5]; let doubled: Vec<i32> = numbers.iter().map(|x| x * 2).collect(); println!("{:?}", doubled); } // 出力 [2, 4, 6, 8, 10] </syntaxhighlight> <br> ==== filterメソッドで要素を絞り込む ==== <code>filter</code> メソッドは、条件に一致する要素のみを抽出する。<br> <syntaxhighlight lang="rust"> fn main() { let numbers = vec![1, 2, 3, 4, 5]; let evens: Vec<&i32> = numbers.iter().filter(|x| *x % 2 == 0).collect(); println!("{:?}", evens); } // 出力 [2, 4] </syntaxhighlight> <br> ==== mapメソッド と filterメソッド を組み合わせる ==== 複数のイテレータメソッドをチェーンすることで、複雑な処理を簡潔に記述できる。<br> <syntaxhighlight lang="rust"> fn main() { let numbers = vec![1, 2, 3, 4, 5]; let result: Vec<i32> = numbers.iter() .filter(|x| *x % 2 == 0) .map(|x| x * 2) .collect(); println!("{:?}", result); } // 出力 [4, 8] </syntaxhighlight> <br><br> __FORCETOC__ [[カテゴリ:Rust]]
Rustの基礎 - 反復処理(for文)
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse