coding-style - 如何将 Vec 部分折叠到位?

标签 coding-style rust

我想遍历 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/

相关文章:

oop - 处理 "cancel button"的最佳 OO 方式

database - 如何使用 Diesel 创建新数据库?

rust - 为什么在将闭包作为特征对象参数传递时需要强制转换?

rust - 我怎样才能让 cargo 自动重新编译更改的文件?

java - 在 Intellij for Java 的单独一行上包装链式方法调用

python - 如何避免由缩进引起的记录器文件中的额外空格

Git:在提交/推送之前通过过滤器运行?

c++ - 包含文件排序策略

rust - Rust类型别名导致生命周期问题

casting - 如何转换我知道是整数的泛型类型?