to_owned().into_iter()和iter()之间的差异,用于在rust中迭代字符串数组

0pizxfdo  于 2022-12-26  发布在  其他
关注(0)|答案(1)|浏览(183)
pub fn capitalize_first(input: &str) -> String {
    let mut c = input.chars();
    match c.next() {
        None => String::new(),
        Some(first) => first.to_uppercase().to_string() + c.as_str(),
    }
}

// Step 2.
// Apply the `capitalize_first` funciton to a slice of string slices.
// Return a vector of strings.
// ["hello", "world"] -> ["Hello", "World"]
pub fn capitalize_words_vector(words: &[&str]) -> Vec<String> {
    words.iter().map(|w| capitalize_first(w)).collect()
}

// Step 3.
// Apply the `capitalize_first` function again to a slice of string slices.
// Return a single string.
// ["hello", " ", "world"] -> "Hello World"
pub fn capitalize_words_string(words: &[&str]) -> String {
    words
        .to_owned()
        .into_iter()
        .map(capitalize_first)
        .collect::<String>()
}

哪种方法更好?
第一个方法是基于我以前的java知识编写的,第二个方法.to_owned().into_iter().map(...)是在sushing solution git repo上看到的
谁能给我解释一下有什么区别,在这种情况下哪一个更好?

mrfwxfqh

mrfwxfqh1#

第一个函数:

pub fn capitalize_words_vector(words: &[&str]) -> Vec<String> {
    words.iter().map(|w| capitalize_first(w)).collect()
}

这个方法和我的方法差不多。你可以通过copied()&&str元素转换成&str来避免w变量。除此之外,我认为这个解决方案很好:

pub fn capitalize_words_vector(words: &[&str]) -> Vec<String> {
    words.iter().copied().map(capitalize_first).collect()
}

第二个功能:

pub fn capitalize_words_string(words: &[&str]) -> String {
    words
        .to_owned()
        .into_iter()
        .map(capitalize_first)
        .collect::<String>()
}

在我看来,这不是最优的。to_owned创建了一个完全不必要的副本,因为你无论如何都要迭代它。所以把一个可迭代对象转换成一个拥有对象,仅仅是为了你可以通过into_iter把它转换回一个迭代器,实际上没有任何意义。
我会使用与第一个完全相同的语义,甚至不需要::<String>,它是从返回类型自动派生的:

pub fn capitalize_words_string(words: &[&str]) -> String {
    words.iter().copied().map(capitalize_first).collect()
}

官方的解决办法似乎是这样说的:

pub fn capitalize_words_string(words: &[&str]) -> String {
    capitalize_words_vector(words).join("")
}

虽然这肯定能起作用,但我不同意它是最优的,因为就像to_owned().into_iter()一样,它创建了一个冗余副本(这意味着它首先计算所有单词,存储它们,然后再次使用它们。iter().copied().map(capitalize_first)不需要迭代两次,它是完全流式的)。

重要提示:我在这里所做的关于性能的声明纯粹是启发式的。如果这是一个真实的世界中的问题,请不要*执行启发式性能分析。而是做一些实际的基准测试。编译器是神奇的,很多时候像这里所谈论的改进并不重要,因为编译器已经优化了它。不要浪费时间在优化上,而不先进行基准测试,然后基准测试您的优化是否实际上是优化**。

在这个特定的案例中,我认为官方的解决方案是“最干净的”,因为它有最少的代码重复。代码重复,以及可维护性,在大多数真实的世界的项目中是一个比性能的最后2%更重要的指标。我见过太多的项目因为可维护性问题而死亡,每一次都让我痛苦。

相关问题