0Pricing
Learn Rust Coding · 课时

计数和分组

掌握常见的基于映射的模式。

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

计数

一个非常常见的任务是统计集合中每个值出现了多少次。

从值映射到计数的 HashMap 是很自然的工具。键是项目,值是它的累计次数。

计数模式

对于每个项目,查找它对应的位置,将默认值设为零,然后加一。

entry API 可以将这些操作简洁地写在一行中。这个模式适用于任何可计数的项目。

use std::collections::HashMap;

fn main() {
    let mut counts = HashMap::new();
    for n in [1, 1, 2, 3, 3, 3] {
        *counts.entry(n).or_insert(0) += 1;
    }
    println!("threes: {}", counts[&3]);
}

统计字符

字符串由字符组成,因此您可以用同样的方式统计字母频率。

使用 chars() 进行迭代,并将每个字符累计到映射中。

use std::collections::HashMap;

fn main() {
    let mut freq = HashMap::new();
    for c in "banana".chars() {
        *freq.entry(c).or_insert(0) += 1;
    }
    println!("a: {}, n: {}", freq[&'a'], freq[&'n']);
}

统计单词

要统计单词,请使用 split_whitespace 按空白字符拆分句子。

每个片段都会成为一个键。这是简单的单词频率分析器的基础。

use std::collections::HashMap;

fn main() {
    let text = "go go stop go";
    let mut counts = HashMap::new();
    for w in text.split_whitespace() {
        *counts.entry(w).or_insert(0) += 1;
    }
    println!("go: {}", counts["go"]);
}

查找最大计数

获得计数后,遍历各项并跟踪最高值,即可找出出现频率最高的项目。

您可以将每个条目的计数与目前为止见过的最佳值进行比较。

use std::collections::HashMap;

fn main() {
    let mut counts = HashMap::new();
    for c in "aabbbc".chars() {
        *counts.entry(c).or_insert(0) += 1;
    }
    let top = counts.iter().max_by_key(|(_, &v)| v).unwrap();
    println!("most common: {}", top.0);
}

对项目分组

分组会将具有相同属性的项目放入同一组。

使用从分组键映射到成员 Vec 的 HashMap。entry API 在首次使用时会将默认值设为空向量。

use std::collections::HashMap;

fn main() {
    let mut groups: HashMap<bool, Vec<i32>> = HashMap::new();
    for n in 1..=6 {
        groups.entry(n % 2 == 0).or_default().push(n);
    }
    println!("evens: {:?}", groups[&true]);
}

按首字母分组

一种自然的分组键是单词的第一个字符。

提取该字符,然后将每个单词推入相应的分组中。

use std::collections::HashMap;

fn main() {
    let words = ["apple", "avocado", "banana"];
    let mut by_letter: HashMap<char, Vec<&str>> = HashMap::new();
    for w in words {
        let first = w.chars().next().unwrap();
        by_letter.entry(first).or_default().push(w);
    }
    println!("a-words: {}", by_letter[&'a'].len());
}

按长度分组

您可以按照任意计算出的属性进行分组,例如每个单词的长度。

这里的键是一个数字,每个分组会收集具有该长度的单词。

use std::collections::HashMap;

fn main() {
    let words = ["hi", "yo", "hey", "hello"];
    let mut by_len: HashMap<usize, Vec<&str>> = HashMap::new();
    for w in words {
        by_len.entry(w.len()).or_default().push(w);
    }
    println!("len 2: {}", by_len[&2].len());
}

统计唯一项目

要统计不重复的值,可以将集合与映射结合使用。或者直接收集到 HashSet 中,再读取其长度。

这样就能得到不同项目的数量,而不会重复计算相同项目。

use std::collections::HashSet;

fn main() {
    let visits = ["sam", "mia", "sam", "leo", "mia"];
    let unique: HashSet<&str> = visits.iter().copied().collect();
    println!("unique visitors: {}", unique.len());
}

报告结果

完成计数或分组后,遍历映射以输出报告。

请记住,顺序未作规定;如果需要稳定的输出,请先对键进行排序。

use std::collections::HashMap;

fn main() {
    let mut counts = HashMap::new();
    for c in "abca".chars() {
        *counts.entry(c).or_insert(0) += 1;
    }
    let mut keys: Vec<_> = counts.keys().collect();
    keys.sort();
    for k in keys {
        println!("{}: {}", k, counts[k]);
    }
}

按组求和

除了收集成员,您还可以进行聚合,例如按键对值求和。

将位置的默认值设为零,然后加上每个项目的值,就像计数一样,只不过这里处理的是实际数值。

use std::collections::HashMap;

fn main() {
    let sales = [("a", 10), ("b", 5), ("a", 3)];
    let mut totals: HashMap<&str, i32> = HashMap::new();
    for (k, amount) in sales {
        *totals.entry(k).or_insert(0) += amount;
    }
    println!("a total: {}", totals["a"]);
}

快速检查

您希望按照单词的首字母将单词分组到不同分组中。

回顾

您使用 entry 模式统计了项目、字符和单词,并找出了出现频率最高的值。

您按字母和长度将项目分到 Vec 分组中,并使用 HashSet 统计了不重复的值。

常见问题解答

「计数和分组」课时是免费的吗?

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

「计数和分组」这节课中我会学到什么?

掌握常见的基于映射的模式。 你通过在浏览器中直接运行的动手代码来练习 Learn Rust Coding,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

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

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

「计数和分组」课时需要多长时间?

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

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

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

此课程中的所有课时

  1. 构建 HashMap
  2. Entry API 与默认值
  3. 使用 HashSet
  4. 计数和分组
← 返回 Learn Rust Coding