string - 交替使用 str 和 String

标签 string rust lifetime

假设我正在尝试使用 &str 在 Rust 中做一个奇特的零拷贝解析器,但有时我需要修改文本(例如实现变量替换)。我真的很想做这样的事情:

fn main() {
    let mut v: Vec<&str> = "Hello there $world!".split_whitespace().collect();

    for t in v.iter_mut() {
        if (t.contains("$world")) {
            *t = &t.replace("$world", "Earth");
        }
    }

    println!("{:?}", &v);
}

当然,t.replace() 返回的 String 生命周期不够长。有解决这个问题的好方法吗?也许有一种类型意味着“理想情况下是 &str 但如果需要的话是 String”?或者也许有一种方法可以使用生命周期注释来告诉编译器返回的 String 应该保持事件状态直到 main() 结束(或者具有与v)?

最佳答案

Rust 以 Cow 的形式提供了您想要的东西(写入时克隆)类型。

use std::borrow::Cow;

fn main() {
    let mut v: Vec<_> = "Hello there $world!".split_whitespace()
                                             .map(|s| Cow::Borrowed(s))
                                             .collect();

    for t in v.iter_mut() {
        if t.contains("$world") {
            *t.to_mut() = t.replace("$world", "Earth");
        }
    }

    println!("{:?}", &v);
}

正如@sellibitze 正确指出的那样,to_mut() 创建了一个新的String,它导致堆分配存储之前借用的值。如果你确定你只有借用的字符串,那么你可以使用

*t = Cow::Owned(t.replace("$world", "Earth"));

如果 Vec 包含 Cow::Owned 元素,这仍然会丢弃分配。您可以使用以下非常脆弱和不安全代码来防止这种情况(它直接对 UTF-8 字符串进行基于字节的操作,并依赖于替换恰好是完全相同的字节数这一事实。 ) 在你的 for 循环中。

let mut last_pos = 0; // so we don't start at the beginning every time
while let Some(pos) = t[last_pos..].find("$world") {
    let p = pos + last_pos; // find always starts at last_pos
    last_pos = pos + 5;
    unsafe {
        let s = t.to_mut().as_mut_vec(); // operating on Vec is easier
        s.remove(p); // remove $ sign
        for (c, sc) in "Earth".bytes().zip(&mut s[p..]) {
            *sc = c;
        }
    }
}

请注意,这完全是为“$world”->“Earth”映射量身定制的。任何其他映射都需要在不安全代码中仔细考虑。

关于string - 交替使用 str 和 String,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31240091/

相关文章:

rust - 有没有办法将类型名称放入 Rust 宏中?

closures - 从闭包填充集合时类型不匹配 "bound lifetime parameter"与 "concrete lifetime"

reference - 为什么我不能从闭包中返回对外部变量的可变引用?

multithreading - 如何将对堆栈变量的引用传递给线程?

python - 在Python中解析包含反斜杠的字符串以列出

string - Scala、模式匹配、字符串

sql - 如何在 SQL Server 中将空字符串 (' ' ) 插入小数或数字?

Java 在字符串中找到某个字符后插入空格

hashmap - 使用rust 的字符串键控 HashMap?

rust - 如何销毁范围内的引用?