言語
日本語
English

Caution

お使いのブラウザはJavaScriptが無効になっております。
当サイトでは検索などの処理にJavaScriptを使用しています。
より快適にご利用頂くため、JavaScriptを有効にしたうえで当サイトを閲覧することをお勧めいたします。

Rust辞典

  1. トップページ
  2. Rust辞典
  3. Iterator::enumerate() / zip() / flat_map()

Iterator::enumerate() / zip() / flat_map()

対応: Rust 1.0(2015)

Rustのイテレータには、インデックス付きで列挙する『enumerate()』、2つのイテレータを組み合わせる『zip()』、ネストを平坦化しながら変換する『flat_map()』などがあります。

構文

// enumerate(): インデックスと要素のタプルを返します。
for (i, val) in vec!["a", "b", "c"].iter().enumerate() {
    println!("{}: {}", i, val);
}

// zip(): 2つのイテレータを組み合わせてタプルのイテレータにします。
let keys = vec!["a", "b", "c"];
let vals = vec![1, 2, 3];
let pairs: Vec<(_, _)> = keys.iter().zip(vals.iter()).collect();

// flat_map(): 変換してネストをフラット化します。
let words = vec!["碇シンジ 綾波レイ", "惣流アスカ 渚カヲル"];
let chars: Vec<&str> = words.iter().flat_map(|s| s.split_whitespace()).collect();

// flatten(): ネストしたイテレータを平坦化します。
let nested = vec![vec![1, 2], vec![3, 4], vec![5]];
let flat: Vec<i32> = nested.into_iter().flatten().collect();

メソッド一覧

メソッド概要
iter.enumerate()(index, value)のタプルを返すイテレータを生成します。
iter.zip(other)2つのイテレータを組み合わせて(a, b)のタプルを返します。
iter.flat_map(|x| ...)変換結果がイテレータの場合にフラット化します。
iter.flatten()ネストしたイテレータを一段階フラット化します。
iter.chain(other)2つのイテレータを連結して1つのイテレータにします。
iter.take(n)先頭からn個の要素だけを取り出します。
iter.skip(n)先頭n個の要素をスキップします。
iter.step_by(n)n個おきに要素を取り出します。
iter.rev()逆順にするイテレータを返します(DoubleEndedIteratorが必要)。
iter.peekable()次の要素を消費せずにpeek()で確認できるイテレータを返します。

サンプルコード

sample_iter_enumerate_zip_flatmap.rs
fn main() {
    // enumerate(): インデックス付きでループします。
    let pilots = vec!["碇シンジ", "綾波レイ", "惣流アスカ"];
    for (i, pilot) in pilots.iter().enumerate() {
        println!("{}: {}", i, pilot);
    }

    // enumerate() で番号付きリストを作ります。
    let numbered: Vec<String> = pilots.iter()
        .enumerate()
        .map(|(i, p)| format!("{}. {}", i + 1, p))
        .collect();
    println!("numbered: {:?}", numbered);

    // zip(): 2つのVecを組み合わせます。
    let names = vec!["碇シンジ", "綾波レイ", "惣流アスカ"];
    let scores = vec![85, 90, 92];
    let combined: Vec<(_, _)> = names.iter().zip(scores.iter()).collect();
    println!("zip: {:?}", combined);

    // zip() で名前とBGMを対応させます。
    let bgms = vec!["Beautiful World", "残酷な天使のテーゼ", "魂のルフラン"];
    let name_bgm: Vec<(_, _)> = names.iter().zip(bgms.iter()).collect();
    println!("name-bgm: {:?}", name_bgm);

    // zip() で HashMap を作ります。
    use std::collections::HashMap;
    let map: HashMap<_, _> = names.iter().zip(scores.iter()).collect();
    println!("zip to HashMap: {:?}", map);

    // flat_map(): 各文字列を単語に分割してフラット化します。
    let sentences = vec!["碇シンジ 綾波レイ 惣流アスカ", "渚カヲル 葛城ミサト"];
    let words: Vec<&str> = sentences.iter().flat_map(|s| s.split_whitespace()).collect();
    println!("flat_map words: {:?}", words);

    // flatten(): ネストしたVecを平坦化します。
    let nested = vec![vec![1, 2, 3], vec![4, 5], vec![6]];
    let flat: Vec<i32> = nested.into_iter().flatten().collect();
    println!("flatten: {:?}", flat);

    // chain(): 2つのイテレータを連結します。
    let a = vec![1, 2, 3];
    let b = vec![4, 5, 6];
    let chained: Vec<i32> = a.iter().chain(b.iter()).copied().collect();
    println!("chain: {:?}", chained);

    // take() と skip() です。
    let v: Vec<i32> = (1..=10).collect();
    let first3: Vec<_> = v.iter().take(3).collect();
    let skip3: Vec<_> = v.iter().skip(3).collect();
    println!("take(3): {:?}", first3);
    println!("skip(3): {:?}", skip3);
}
rustc iter_enumerate_zip_flatmap.rs
./iter_enumerate_zip_flatmap
0: 碇シンジ
1: 綾波レイ
2: 惣流アスカ
numbered: ["1. 碇シンジ", "2. 綾波レイ", "3. 惣流アスカ"]
zip: [("碇シンジ", 85), ("綾波レイ", 90), ("惣流アスカ", 92)]
name-bgm: [("碇シンジ", "Beautiful World"), ("綾波レイ", "残酷な天使のテーゼ"), ("惣流アスカ", "魂のルフラン")]
zip to HashMap: {"碇シンジ": 85, "綾波レイ": 90, "惣流アスカ": 92}
flat_map words: ["碇シンジ", "綾波レイ", "惣流アスカ", "渚カヲル", "葛城ミサト"]
flatten: [1, 2, 3, 4, 5, 6]
chain: [1, 2, 3, 4, 5, 6]
take(3): [1, 2, 3]
skip(3): [4, 5, 6, 7, 8, 9, 10]

概要

『zip()』は短い方のイテレータが尽きると終了します。長さが違う場合も安全に処理されます。両方の全要素を処理したい場合は『itertools』クレートの『zip_longest()』が使えます。

『flat_map()』は『map().flatten()』と同等です。ネストしたOptionやResultを処理するときにも便利です(例: 『iter.flat_map(|x| x.ok())』でエラーを無視して成功値だけ取り出せます)。

変換・絞り込みは『Iterator::map() / filter()』を参照してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。