在 Rust 中构建新字符串的有效方法

Efficient ways to build new Strings in Rust

最近刚开始学习Rust,一直在乱码一些代码。我想创建一个简单的函数,从字符串中删除元音并 returns 一个新的字符串。下面的代码起作用了,但我担心这是否真的是这种语言中有效的典型方法,或者我是否遗漏了什么...

// remove vowels by building a String using .contains() on a vowel array
fn remove_vowels(s: String) -> String {
    let mut no_vowels: String = String::new();
    for c in s.chars() {
        if !['a', 'e', 'i', 'o', 'u'].contains(&c) {
            no_vowels += &c.to_string();
        }
    }
    return no_vowels;
}

首先,使用 to_string() 构造一个新的字符串,然后使用 & 来借用似乎不太合适。是否有更简单的方法将字符附加到字符串,或者这是唯一的方法吗?或者我应该完全重写它并使用循环按长度而不是字符数组遍历输入的字符串吗?

另外,我听说在 Rust 中很流行不使用 return 语句而是让最后一个表达式 return 来自函数的值。此处是否需要我的 return 语句,或者是否有更简洁的方法来 return 该值遵循约定?

您可以在字符迭代器上使用 collect 来创建字符串。您可以使用 filter.

过滤掉不需要的字符
// remove vowels by building a String using .contains() on a vowel array
fn remove_vowels(s: &str) -> String {
    s.chars()
        .filter(|c| !['a', 'e', 'i', 'o', 'u'].contains(c))
        .collect()
}

playground

如果这是在性能关键区域,那么由于您知道要删除的字符是 utf8 中的单个字节,因此可以直接从字节中删除它们。这意味着你可以写类似

fn remove_vowels(s: &str) -> String {
    String::from_utf8(
        s.bytes()
            .filter(|c| ![b'a', b'e', b'i', b'o', b'u'].contains(c))
            .collect()
    ).unwrap()
}

哪个可能更有效率。 playground

如果您像您的示例那样使用原始 String,则可以使用 retain() 就地删除元音,这将避免分配新字符串:

fn remove_vowels(mut s: String) -> String {
    s.retain(|c| !['a', 'e', 'i', 'o', 'u'].contains(&c));
    s
}

查看它在 playground 上的工作情况。旁注:您可能还想考虑大写元音。