如何在Rust中用链式调用编写简洁的后缀和函数?
Rust 简洁实现后缀和函数的链式调用方案
第一段代码失败的原因
你以为两次rev()相互抵消导致失效?其实不是。问题出在map里捕获了可变变量sum,此时map返回的迭代器闭包是FnMut类型,而这种Map迭代器没有实现DoubleEndedIterator trait,所以根本无法调用后续的rev()方法——这才是代码无法编译运行的核心原因。
第二段代码的冗余问题
第二段代码通过中间collect()转成Vec再反转,确实能运行,但两次collect()会额外分配内存,效率不高,写法也不够简洁。
更简洁的实现方案
方案1:用scan替代map,保留反转思路
scan迭代器可以携带可变状态,并且当原迭代器实现DoubleEndedIterator时,Scan迭代器也会自动实现该trait,这样就能直接链式调用rev(),无需中间collect():
fn suffix_sum(vec: &[i32]) -> Vec<i32> { vec.iter() .rev() .scan(0, |state, &val| { *state += val; Some(*state) }) .rev() .collect() }
这里把参数从&Vec<i32>改成&[i32],让函数更通用,能接受任意切片类型。
方案2:利用总和直接计算,无需反转
后缀和的本质是:第一个元素是数组总和,第二个是总和减去第一个元素,第三个是总和减去前两个元素……基于这个逻辑,我们可以一次遍历完成计算,效率更高:
fn suffix_sum(vec: &[i32]) -> Vec<i32> { let total: i32 = vec.iter().sum(); vec.iter() .scan(total, |state, &val| { let res = *state; *state -= val; Some(res) }) .collect() }
这个写法完全不需要反转迭代器,只需要一次遍历生成结果,代码更简洁,性能也更好。
内容的提问来源于stack exchange,提问作者Overclouds
相关产品推荐
相关产品推荐

