外观
第 5 节:Vec 高频 API
push/pop/len/iter 是家常便饭,下面这些才是真实项目里的"效率担当"。
extend:批量追加 ⭐
rust
let mut numbers = vec![1, 2, 3];
numbers.extend([4, 5]);
// [1, 2, 3, 4, 5]把一个迭代器/数组/另一个 Vec 整体追加进去,代替"循环 + push"。注意:追加的是元素,不是"整个 Vec 塞进去"(那是 push(vec) 干的事——想要嵌套就 push)。
retain:留下符合条件的(原地删) ⭐
rust
let mut numbers = vec![1, 2, 3, 4, 5, 6];
numbers.retain(|n| n % 2 == 0);
// [2, 4, 6]"删掉所有不符合条件的"——原地操作,不用新建 Vec。比"收集符合的再替换"省事:
rust
// 笨办法(第 7 章雷区 7 的风格)
let evens: Vec<_> = numbers.iter().filter(|n| *n % 2 == 0).copied().collect();
numbers = evens;
// retain 一行(推荐)
numbers.retain(|n| n % 2 == 0);dedup:去掉相邻重复 ✨
rust
let mut numbers = vec![1, 1, 2, 2, 2, 3, 1];
numbers.dedup();
// [1, 2, 3, 1]——注意:只去掉"相邻"的重复,最后的 1 保留去重前先 sort(),dedup 才"全去重"。统计"有哪些不同的值"的偷懒写法:sort + dedup。
windows / chunks:滑动窗口 / 分组 ✨
rust
let numbers = [1, 2, 3, 4, 5];
for window in numbers.windows(3) {
// [1,2,3] → [2,3,4] → [3,4,5]——每次滑一格
}
for chunk in numbers.chunks(2) {
// [1,2] → [3,4] → [5]——不重叠,最后一段可能不满
}windows(n):连续 n 个一组,滑动一步——算"连续三天的平均温度"就用它chunks(n):不重叠分组——批量处理(每 100 条一组存文件)就用它
swap_remove:快速删除(顺序无所谓时) ⭐
rust
let mut numbers = vec![10, 20, 30, 40];
let removed = numbers.swap_remove(1);
// removed = 20,numbers = [10, 40, 30]删除中间的元素:remove(i) 要把后面的全部往前挪(O(n));swap_remove(i) 把最后一个搬过来顶替(O(1))——代价是顺序会乱。"顺序无所谓"的集合(比如 Set 的底层、随机选一个删),用它快得多。
insert / remove:中间插入 / 删除 ⭐
rust
let mut letters = vec!["a", "b", "c"];
letters.insert(1, "x"); // ["a", "x", "b", "c"]
let b = letters.remove(2); // b = "b",letters = ["a", "x", "c"]注意:insert/remove 都是 O(n) 的(要挪元素)。频繁在中间插删,考虑 VecDeque(两头快)。
truncate:截断到前 n 个 ✨
rust
let mut numbers = vec![1, 2, 3, 4, 5];
numbers.truncate(2);
// [1, 2]"只保留前 N 个"——比如日志只留最近 100 条。比"循环 pop 到长度"快得多。
记忆口诀
批量 extend,条件删 retain,去重先 sort 再 dedup,窗口 windows,分组 chunks,快删 swap_remove,截断 truncate。 改 Vec 前先想:是"追加、筛选、去重、分组、快删"哪种?——方法就在名字里。
常见误用
windows/chunks会 panic 吗:windows(n)的n为 0 会 panic;n > len不 panic(windows 空、chunks 返回一个不满的段)retain的闭包返回 true 是"留下":和filter语义一致,别记反dedup只去相邻重复:期望"全局去重"却得到"隔一个还在"——先sort或换HashSet(第 7 章)