Caution
お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。
Iterator::fold() / any() / all() / find()
Rustのイテレータには、累積処理を行う『fold()』、条件判定の『any()』『all()』、要素の検索をする『find()』『position()』などの終端操作があります。
構文
// fold(): 初期値とクロージャで累積処理します。 let sum = vec![1, 2, 3, 4, 5].iter().fold(0, |acc, x| acc + x); // 15 // any(): 1つでも条件を満たす要素があればtrueを返します。 let has_even = vec![1, 3, 5, 6].iter().any(|x| x % 2 == 0); // true // all(): 全ての要素が条件を満たせばtrueを返します。 let all_pos = vec![1, 2, 3].iter().all(|x| *x > 0); // true // find(): 最初に条件を満たした要素をOption<&T>で返します。 let first_even = vec![1, 3, 4, 6].iter().find(|&&x| x % 2 == 0); // Some(4) // position(): 最初に条件を満たした要素のインデックスをOption<usize>で返します。 let idx = vec![1, 3, 4, 6].iter().position(|&x| x % 2 == 0); // Some(2)
メソッド一覧
| メソッド | 概要 |
|---|---|
| iter.fold(init, |acc, x| ...) | 初期値から始めてクロージャで累積した結果を返します。 |
| iter.reduce(|acc, x| ...) | fold()と似ていますが初期値なし(最初の要素が初期値)。Option を返します。 |
| iter.any(|x| ...) | 1つでも条件を満たす要素があればtrueを返します。 |
| iter.all(|x| ...) | 全要素が条件を満たす場合trueを返します(空の場合はtrue)。 |
| iter.find(|x| ...) | 最初に条件を満たした要素をOption<&T>で返します。 |
| iter.find_map(|x| ...) | 最初にSomeを返したクロージャの結果をOption<T>で返します。 |
| iter.position(|x| ...) | 最初に条件を満たした要素のインデックスをOption<usize>で返します。 |
| iter.rposition(|x| ...) | 末尾から検索してインデックスをOption<usize>で返します。 |
| iter.scan(state, |s, x| ...) | 内部状態を持ちながら変換するイテレータを返します。 |
サンプルコード
fn main() {
let numbers = vec![1, 2, 3, 4, 5];
// fold(): 合計を計算します。
let sum = numbers.iter().fold(0, |acc, &x| acc + x);
println!("fold(合計): {}", sum); // 15
// fold(): 最大値を求めます。
let max = numbers.iter().fold(i32::MIN, |acc, &x| acc.max(x));
println!("fold(最大値): {}", max); // 5
// fold(): 文字列を結合します。
let words = vec!["Hello", " ", "World"];
let sentence = words.iter().fold(String::new(), |mut acc, s| {
acc.push_str(s);
acc
});
println!("fold(文字列結合): {}", sentence);
// reduce(): 初期値なしで累積します。
let product = numbers.iter().copied().reduce(|acc, x| acc * x);
println!("reduce(積): {:?}", product); // Some(120)
// any(): 条件を満たす要素があるか確認します。
let has_negative = numbers.iter().any(|&x| x < 0);
let has_five = numbers.iter().any(|&x| x == 5);
println!("負の数あり?: {}", has_negative); // false
println!("5あり?: {}", has_five); // true
// all(): 全要素が条件を満たすか確認します。
let all_positive = numbers.iter().all(|&x| x > 0);
let all_even = numbers.iter().all(|&x| x % 2 == 0);
println!("全て正?: {}", all_positive); // true
println!("全て偶数?: {}", all_even); // false
// find(): 最初に条件を満たした要素を見つけます。
let first_even = numbers.iter().find(|&&x| x % 2 == 0);
println!("最初の偶数: {:?}", first_even); // Some(2)
let not_found = numbers.iter().find(|&&x| x > 100);
println!("100より大きい数: {:?}", not_found); // None
// position(): インデックスを取得します。
let pos = numbers.iter().position(|&x| x == 3);
println!("3のインデックス: {:?}", pos); // Some(2)
// find_map(): 変換しながら最初のSomeを取り出します。
let strs = vec!["abc", "42", "xyz"];
let first_num = strs.iter().find_map(|s| s.parse::<i32>().ok());
println!("最初の数値: {:?}", first_num); // Some(42)
}
概要
『any()』と『all()』は短絡評価(short-circuit)を行います。『any()』は最初にtrueを返す要素が見つかった時点で、『all()』は最初にfalseを返す要素が見つかった時点で処理を終了します。
『fold()』はあらゆる集計処理を表現できる汎用的な操作です。ただし、合計には『sum()』、最大値には『max()』など専用の操作がある場合はそちらを使う方が意図が明確です。
収集・集計の基本は『Iterator::collect() / count() / sum()』を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。