0Pricing
Learn Rust Coding · 课时

map、filter、collect

转换序列

map、filter、collect 是 CoddyKit 上的免费 Learn Rust Coding 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Learn Rust Coding 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Learn Rust Coding 课程共包含 4 节课。

转换序列

迭代器流水线中的大部分工作由三个方法完成:map 转换每个项目,filter 保留部分项目,而 collect 将结果收集到集合中。

它们结合起来,可以用简短易读的链式操作替代许多手动循环。

map:一进一出

map 会对每个项目应用闭包,并生成转换后的值。项目数量保持不变,只有值会发生变化。

它是惰性的,因此只有在迭代器被消费时,闭包才会运行。

fn main() {
    let nums = vec![1, 2, 3];
    let doubled: Vec<i32> = nums.iter().map(|x| x * 2).collect();
    println!("{:?}", doubled);
}

map 可以改变类型

map 的输出类型不必与输入类型相同。在这里,我们将数字转换为字符串。

这使 map 非常适合将数据从一种形式转换为另一种形式。

fn main() {
    let nums = vec![1, 2, 3];
    let labels: Vec<String> = nums.iter().map(|x| format!("n{}", x)).collect();
    println!("{:?}", labels);
}

filter:保留所需内容

filter 接收一个返回 bool 的闭包。闭包返回 true 的项目会被保留,其余项目会被丢弃。

闭包接收的是引用,因此您通常需要使用 * 进行解引用,或使用模式匹配。

fn main() {
    let nums = vec![1, 2, 3, 4, 5, 6];
    let evens: Vec<i32> = nums.into_iter().filter(|x| x % 2 == 0).collect();
    println!("{:?}", evens);
}

串联 map 和 filter

您可以自由地串联适配器。顺序很重要:每个项目都会从上到下流经整个链。

这里我们先保留偶数,再对保留下来的数字求平方。

fn main() {
    let result: Vec<i32> = (1..=6)
        .filter(|x| x % 2 == 0)
        .map(|x| x * x)
        .collect();
    println!("{:?}", result);
}

将结果 collect 到 Vec

collect 会消费迭代器并构建一个集合。由于可能有多种集合类型,您通常需要标注目标类型。

涡轮鱼语法 collect::<Vec<_>>() 可以替代变量类型标注。

fn main() {
    let squares = (1..=4).map(|x| x * x).collect::<Vec<i32>>();
    println!("{:?}", squares);
}

将结果 collect 到 String

collect 不仅限于向量。由 char 组成的迭代器可以收集到 String 中。

Rust 会根据目标类型决定如何组装这些项目。

fn main() {
    let shouted: String = "hello".chars().map(|c| c.to_ascii_uppercase()).collect();
    println!("{}", shouted);
}

将结果 collect 到 HashMap

由键值元组组成的迭代器可以收集到 HashMap 中。您可以使用 zip 配对项目,或在 map 中构建元组。

这是根据两个并行序列构建查找表的一种简洁方式。

use std::collections::HashMap;

fn main() {
    let map: HashMap<i32, i32> = (1..=3).map(|x| (x, x * x)).collect();
    println!("{:?}", map.get(&2));
}

组合三种操作

典型的处理流水线读起来就像一句话:获取项目、过滤项目、转换项目、收集项目。

这里我们保留长度超过三个字母的单词,并将它们转换为大写。

fn main() {
    let words = vec!["hi", "rust", "go", "code"];
    let kept: Vec<String> = words
        .into_iter()
        .filter(|w| w.len() > 3)
        .map(|w| w.to_uppercase())
        .collect();
    println!("{:?}", kept);
}

filter_map:同时过滤和转换

filter_map 会应用一个返回 Option 的闭包。Some(v) 会被保留并解包,而 None 会被丢弃。

解析数据时,这种方法尤其有用,因为某些输入可能无效。

fn main() {
    let inputs = vec!["1", "two", "3"];
    let nums: Vec<i32> = inputs
        .into_iter()
        .filter_map(|s| s.parse::<i32>().ok())
        .collect();
    println!("{:?}", nums);
}

这种模式为何更出色

map/filter/collect 流水线是声明式的:它们说明您想要什么,而不是说明应如何循环。它们可以避免差一错误和中间的可变状态。

此外,得益于惰性求值,各步骤之间不会构建临时向量。

快速检查

检查您对序列转换的了解。

回顾

现在您已经可以构建真正的迭代器流水线:

  • map 转换每个项目,并且可以改变其类型
  • filter 保留谓词为 true 的项目
  • collect 将结果收集到 Vec、String、HashMap 等类型中
  • filter_map 使用 Option 在一步中完成过滤和转换

常见问题解答

「map、filter、collect」课时是免费的吗?

是的 — 「map、filter、collect」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Learn Rust Coding 课程的其余内容,请升级到 CoddyKit PRO。 Learn Rust Coding 课程共包含 4 节课。

「map、filter、collect」这节课中我会学到什么?

转换序列 你通过在浏览器中直接运行的动手代码来练习 Learn Rust Coding,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Learn Rust Coding 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Learn Rust Coding 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「map、filter、collect」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Learn Rust Coding 课中编写并运行代码吗?

能。每节 Learn Rust Coding 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. Iterator 特征
  2. map、filter、collect
  3. 适配器与消费者
  4. 自定义迭代器
← 返回 Learn Rust Coding