Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

イテレータ内を検索する

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);
}

関連項目:

std::iter::Iterator::find

std::iter::Iterator::find_map

std::iter::Iterator::position

std::iter::Iterator::rposition