イテレータ内を検索する
Iterator::find は、イテレータを反復処理し、何らかの条件を満たす 最初の値を検索する関数です。条件を満たす値がない場合は、None を返します。 シグネチャは次のとおりです。
pub trait Iterator {
// イテレーション対象の型。
type Item;
// `find` は `&mut self` を受け取るため、呼び出し元は借用され
// 変更される可能性はあるが、消費されない。
fn find<P>(&mut self, predicate: P) -> Option<Self::Item> where
// `FnMut` は、キャプチャされた変数が多くても変更されるだけで、
// 消費されないことを意味する。`&Self::Item` は、クロージャへの
// 引数を参照で受け取ることを表す。
P: FnMut(&Self::Item) -> bool;
}
fn main() { let vec1 = vec![1, 2, 3]; let vec2 = vec![4, 5, 6]; // `vec1.iter()` は `&i32` を生成する。 let mut iter = vec1.iter(); // `vec2.into_iter()` は `i32` を生成する。 let mut into_iter = vec2.into_iter(); // `iter()` は `&i32` を生成し、`find` は `&Item` を述語に渡す。 // `Item = &i32` なので、クロージャ引数の型は `&&i32` になり、 // これをパターンマッチして `i32` までデリファレンスする。 println!("vec1 で 2 を検索: {:?}", iter.find(|&&x| x == 2)); // `into_iter()` は `i32` を生成し、`find` は `&Item` を述語に渡す。 // `Item = i32` なので、クロージャ引数の型は `&i32` になり、 // これをパターンマッチして `i32` までデリファレンスする。 println!("vec2 で 2 を検索: {:?}", into_iter.find(|&x| x == 2)); let array1 = [1, 2, 3]; let array2 = [4, 5, 6]; // `array1.iter()` は `&i32` を生成し、`find` は `&Item` を // 述語に渡す。`Item = &i32` なので、クロージャ引数の型は `&&i32` になる。 println!("array1 で 2 を検索: {:?}", array1.iter().find(|&&x| x == 2)); // `array2.into_iter()` は(Rust 2021 edition 以降)`i32` を生成し、 // `find` は `&Item` を述語に渡す。`Item = i32` なので、 // クロージャ引数の型は `&i32` になる。 println!("array2 で 2 を検索: {:?}", array2.into_iter().find(|&x| x == 2)); }
Iterator::find はアイテムへの参照を返します。しかし、アイテムの_インデックス_が必要な場合は、Iterator::position を使用します。
fn main() { let vec = vec![1, 9, 3, 3, 13, 2]; // `position` はイテレータの `Item` を値で述語に渡す。 // `vec.iter()` は `&i32` を生成するため、述語は `&i32` を受け取り、 // これをパターンマッチして `i32` にデリファレンスする。 let index_of_first_even_number = vec.iter().position(|&x| x % 2 == 0); assert_eq!(index_of_first_even_number, Some(5)); // `vec.into_iter()` は `i32` を生成するため、述語は `i32` を直接受け取る。 let index_of_first_negative_number = vec.into_iter().position(|x| x < 0); assert_eq!(index_of_first_negative_number, None); }