我想遍历 Vec 并组合其中的一些元素。我如何在惯用的 Rust 中做到这一点?
示例:
#[derive(PartialEq, Debug)]
enum Thing { A, B, AandB }
fn combine(v: Vec<Thing>) -> Vec<Thing> {
// idiomatic code here
}
fn main() {
let v = vec![Thing::A, Thing::B];
assert_eq!(vec![Thing::AandB], combine(v));
}
我会怎么做:
使用 Iterator::scan 遍历 Vec,如果 Thing::A 是之前的元素,则将所有出现的 Thing::B 替换为 Thing::AandB。然后我会再次遍历它并删除所有 Thing::As before Thing::AandB。
这看起来 super 复杂和不优雅。
最佳答案
我合并了 swizard 的答案和 Shepmaster 的答案,最终得到了一个就地解决方案,该解决方案递归地运行向量,只有向量是可变的,并且从不移动任何东西两次。不保证运行时或惯用性;)
use Thing::*;
use std::cmp::min;
#[derive(Copy,Clone,PartialEq,Debug)]
enum Thing { A, B, AandB}
fn combine(mut v: Vec<Thing>) -> Vec<Thing> {
fn inner(res: &mut Vec<Thing>, i: usize, backshift: usize) {
match &res[i..min(i+2, res.len())] {
[A, B] => {
res[i - backshift] = AandB;
inner(res, i + 2, backshift + 1);
},
[a, ..] => {
res[i - backshift] = a;
inner(res, i + 1, backshift);
},
[] => res.truncate(i - backshift),
}
};
inner(&mut v, 0, 0);
v
}
fn main() {
let v = vec![A, A, B, AandB, B, A, B, A, B];
assert_eq!(vec![A, AandB, AandB, B, AandB, AandB], combine(v));
let v = vec![A, A, B, AandB, B, A, B, A, A];
assert_eq!(vec![A, AandB, AandB, B, AandB, A, A], combine(v));
}
关于coding-style - 如何将 Vec 部分折叠到位?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28318886/