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

收集

本集目標

學會用 .collect() 把迭代器收集成各種集合型別。

概念說明

平常我們不會花這麼多集數在介紹方法,但迭代器實在太重要了——它是 Rust 日常寫程式碼最常用的工具之一,所以接下來幾集會多花點時間。不過就算介紹了很多方法,一定還是會漏掉不少。有需要的話,請參考官方文件的 Iterator trait 頁面

.collect() —— 迭代器的終點站

前幾集我們建立了迭代器、做了轉換和過濾,但迭代器本身是惰性的(第 15 集會詳細講)——它不會真的執行,直到有人「拉動」它。.collect() 就是最常用的拉動方式:把迭代器的所有元素收集成一個集合。

fn main() {
    let v: Vec<i32> = (1..=5).collect();
}

你可能注意到了——1..=5 是第一章學的 range 語法,它事實上是實作了 Iterator!所以可以直接對它呼叫 .collect() 和其他迭代器方法。

收集成 String

.collect() 不只能收集成 Vec。如果迭代器產出的是 char&str,可以直接收集成 String

fn main() {
    let chars = vec!['R', 'u', 's', 't'];
    let word: String = chars.into_iter().collect();
    println!("{}", word); // "Rust"
}

.last() —— 取最後一個元素

.last() 會消耗整個迭代器,回傳最後一個元素(Option<T>):

fn main() {
    let v = vec![10, 20, 30];
    let last = v.iter().last();
    println!("{:?}", last); // Some(&30)
}

注意它需要走完整個迭代器才能知道最後一個是什麼。

範例程式碼

fn main() {
    // 基本 collect —— Range 轉 Vec
    let numbers: Vec<i32> = (1..=10).collect();
    println!("1 到 10:{:?}", numbers);

    // turbofish 語法
    let numbers2 = (1..=5).collect::<Vec<i32>>();
    println!("turbofish:{:?}", numbers2);

    // 收集成 String
    let greeting: String = vec!['你', '好', '世', '界'].into_iter().collect();
    println!("字串:{}", greeting);

    // .last()
    let last_num = (1..=100).last();
    println!("\n1..=100 的最後一個:{:?}", last_num);

    let empty: Vec<i32> = vec![];
    let last_empty = empty.iter().last();
    println!("空 Vec 的 last:{:?}", last_empty);
}

重點整理

  • range 不僅實作了 IntoIterator,其實它本身就是一個 Iterator
  • .collect() 把迭代器的元素收集成目標集合型別
  • 用型別標註 let v: Vec<i32> 或 turbofish .collect::<Vec<i32>>() 告訴 Rust 目標型別
  • 可以收集成 VecString 等多種型別
  • .last() 消耗整個迭代器,回傳 Some 包裝的最後一個元素