如何用Rust函数式API按空行分割生成&str类型的二维向量?
用Rust函数式API分割Advent of Code 2022第11题的猴子数据块
问题描述
我正在完成Advent of Code 2022第11题,输入为一段&str格式的猴子数据(示例输入如下):
Monkey 0: Starting items: 52, 60, 85, 69, 75, 75 Operation: new = old * 17 Test: divisible by 13 If true: throw to monkey 6 If false: throw to monkey 7 Monkey 1: Starting items: 96, 82, 61, 99, 82, 84, 85 Operation: new = old + 8 Test: divisible by 7 If true: throw to monkey 0 If false: throw to monkey 7 Monkey 2: Starting items: 95, 79 Operation: new = old + 6 Test: divisible by 19 If true: throw to monkey 5 If false: throw to monkey 3
希望用Rust的函数式API(如map、filter、fold等)按空行分割每个猴子的数据块,生成Vec<Vec<&str>>类型的结果,示例输出如下:
[["Monkey 0:", " Starting items: 52, 60, 85, 69, 75, 75", " Operation: new = old * 17", " Test: divisible by 13", " If true: throw to monkey 6", " If false: throw to monkey 7"], [" Monkey 1:", " Starting items: 96, 82, 61, 99, 82, 84, 85", " Operation: new = old + 8", " Test: divisible by 7", " If true: throw to monkey 0", " If false: throw to monkey 7"]]
我已用命令式方式实现,但不清楚如何用更符合Rust风格的函数式方式完成。
函数式实现方案
方案一:用fold逐行构建结果
fn split_monkeys(input: &str) -> Vec<Vec<&str>> { input .lines() .filter(|line| !line.trim().is_empty()) // 过滤所有空白行 .fold(Vec::new(), |mut acc, line| { // 识别猴子起始行,新增子向量 if line.trim_start().starts_with("Monkey") { acc.push(Vec::new()); } // 将当前行加入最后一个猴子的向量中 acc.last_mut().unwrap().push(line); acc }) } // 使用示例 fn main() { let input = "Monkey 0:\n Starting items: 52, 60, 85, 69, 75, 75\n Operation: new = old * 17\n Test: divisible by 13\n If true: throw to monkey 6\n If false: throw to monkey 7\n \n Monkey 1:\n Starting items: 96, 82, 61, 99, 82, 84, 85\n Operation: new = old + 8\n Test: divisible by 7\n If true: throw to monkey 0\n If false: throw to monkey 7\n \n Monkey 2:\n Starting items: 95, 79\n Operation: new = old + 6\n Test: divisible by 19\n If true: throw to monkey 5\n If false: throw to monkey 3"; let monkeys = split_monkeys(input); println!("{:?}", monkeys); }
代码说明
- 过滤空行:通过
lines()拆分输入后,用filter移除所有仅含空白字符的行。 - 折叠构建:用
fold初始化空结果集,遍历每行时:- 判断当前行是否为猴子的起始行(去掉前置空格后以"Monkey"开头),是则新增一个子向量。
- 将当前行追加到结果集的最后一个子向量中。
方案二:用split按块拆分(更简洁)
fn split_monkeys(input: &str) -> Vec<Vec<&str>> { input .split("\n\n") // 按空行直接拆分猴子块 .map(|block| { block .lines() .filter(|line| !line.trim().is_empty()) // 过滤块内的空白行 .collect() }) .collect() }
代码说明
- 块级拆分:
split("\n\n")直接将输入分割为每个猴子对应的文本块。 - 行处理:对每个块拆分行、过滤空行后,收集为
Vec<&str>。 - 结果收集:将所有处理后的块收集为最终的
Vec<Vec<&str>>。
这种写法逻辑更直观,完全遵循函数式风格,推荐使用。
内容的提问来源于stack exchange,提问作者Mlengcivil
相关产品推荐
相关产品推荐

