用Rust中的向量元素替换编号的占位符?

时间:2018-12-30 00:31:43

标签: string replace rust

我有以下内容:

  • 一个Vec<&str>
  • 一个&str,其中可能包含引用向量中元素的$0$1等。

我想获取我的&str的版本,其中所有出现的$i被向量的ith元素替换。因此,如果我有vec!["foo", "bar"]$0$1,结果将是foobar

我的第一个幼稚方法是遍历i = 1..N并搜索并替换每个索引。但是,这是一个非常丑陋且效率低下的解决方案。此外,如果向量中的任何值包含$字符,它都会提供不期望的输出。

在Rust中有更好的方法吗?

2 个答案:

答案 0 :(得分:3)

此解决方案受到Shepmaster's的启发(包括复制的测试用例),但使用replace_all方法简化了事情。

use regex::{Regex, Captures};

fn template_replace(template: &str, values: &[&str]) -> String {
    let regex = Regex::new(r#"\$(\d+)"#).unwrap();
    regex.replace_all(template, |captures: &Captures| {
        values
            .get(index(captures))
            .unwrap_or(&"")
    }).to_string()
}

fn index(captures: &Captures) -> usize {
    captures.get(1)
        .unwrap()
        .as_str()
        .parse()
        .unwrap()
}

fn main() {
    assert_eq!("ab", template_replace("$0$1", &["a", "b"]));
    assert_eq!("$1b", template_replace("$0$1", &["$1", "b"]));
    assert_eq!("moo", template_replace("moo", &[]));
    assert_eq!("abc", template_replace("a$0b$0c", &[""]));
    assert_eq!("abcde", template_replace("a$0c$1e", &["b", "d"]));
    println!("It works!");
}

答案 1 :(得分:2)

我会使用a regex

use regex::Regex; // 1.1.0

fn example(s: &str, vals: &[&str]) -> String {
    let r = Regex::new(r#"\$(\d+)"#).unwrap();

    let mut start = 0;
    let mut new = String::new();

    for caps in r.captures_iter(s) {
        let m = caps.get(0).expect("Regex group 0 missing");
        let d = caps.get(1).expect("Regex group 1 missing");
        let d: usize = d.as_str().parse().expect("Could not parse index");

        // Copy non-placeholder
        new.push_str(&s[start..m.start()]);
        // Copy placeholder
        new.push_str(&vals[d]);

        start = m.end()
    }

    // Copy non-placeholder
    new.push_str(&s[start..]);

    new
}

fn main() {
    assert_eq!("ab", example("$0$1", &["a", "b"]));
    assert_eq!("$1b", example("$0$1", &["$1", "b"]));
    assert_eq!("moo", example("moo", &[]));
    assert_eq!("abc", example("a$0b$0c", &[""]));
}

另请参阅: