如何在循环中重复进行字符串替换?

Boo*_*oon 2 string replace ownership rust

我正在编写一种方法来循环遍历(from, to)地图并执行多轮tmp = tmp.replace(from, to). 我仍在尝试掌握 Rust 的所有权概念

#[macro_use]
extern crate lazy_static;

use std::collections::HashMap;

lazy_static! {
    static ref REPLACEMENTS: HashMap<&'static str, &'static str> = {
        let mut m = HashMap::new();
        m.insert("abc", "def");
        m.insert("com", "org");
        m
    };
}

fn replace_path_name(path: &str) -> &str {
    let mut tmp = path;

    for (from, to) in REPLACEMENTS.iter() {
        let a = *from;
        let b = *to;

        tmp = tmp.replace(a, b);
    }

    tmp
}

fn main() {}
Run Code Online (Sandbox Code Playgroud)

这段代码让我...

#[macro_use]
extern crate lazy_static;

use std::collections::HashMap;

lazy_static! {
    static ref REPLACEMENTS: HashMap<&'static str, &'static str> = {
        let mut m = HashMap::new();
        m.insert("abc", "def");
        m.insert("com", "org");
        m
    };
}

fn replace_path_name(path: &str) -> &str {
    let mut tmp = path;

    for (from, to) in REPLACEMENTS.iter() {
        let a = *from;
        let b = *to;

        tmp = tmp.replace(a, b);
    }

    tmp
}

fn main() {}
Run Code Online (Sandbox Code Playgroud)

额外的ab是我试图理解为什么 Rust 创造fromto成为&&str

She*_*ter 5

第一个问题是你的返回值:&str。您正在返回对某物的引用,但是什么将拥有该值呢?您不能返回对局部变量的引用。

第二个问题是 的返回类型str::replace,它是 a String,而不是 a &str。这就是错误消息的原因:您试图将 a 存储在只能存储Stringa 的变量中。&str你不能这样做。

简单的修复并不是最有效的;无条件创建一个String

fn replace_path_name(path: &str) -> String {
    let mut tmp = String::from(path);

    for (from, to) in REPLACEMENTS.iter() {
        tmp = tmp.replace(from, to);
    }

    tmp
}
Run Code Online (Sandbox Code Playgroud)

在某些情况下,您还可以使用类似的类型Cow来节省一点分配:

use std::borrow::Cow;

fn replace_path_name(path: &str) -> String {
    let mut tmp = Cow::from(path);

    for (from, to) in &*REPLACEMENTS {
        tmp = tmp.replace(from, to).into();
    }

    tmp.into()
}
Run Code Online (Sandbox Code Playgroud)

甚至可以返回,以便在不存在替换的情况下不会发生分配:

use std::borrow::Cow;

fn replace_path_name(path: &str) -> Cow<str> {
    let mut tmp = Cow::from(path);

    for (from, to) in &*REPLACEMENTS {
        tmp = tmp.replace(from, to).into();
    }

    tmp
}
Run Code Online (Sandbox Code Playgroud)

或者使用以下功能等效Iterator::fold

use std::borrow::Cow;

fn replace_path_name(path: &str) -> Cow<str> {
    REPLACEMENTS
        .iter()
        .fold(Cow::from(path), |s, (from, to)| s.replace(from, to).into())
}
Run Code Online (Sandbox Code Playgroud)

不幸的是str::replace没有返回Cow<str>. 如果确实如此,并且不进行替换,则不会进行分配。

也可以看看: