Rust 字符串连接 [英] Rust String concatenation

查看:161
本文介绍了Rust 字符串连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我本周开始使用 Rust 进行编程,但在理解字符串的工作方式时遇到了很多问题.

I started programming with Rust this week and I am having a lot of problems understanding how Strings work.

现在,我正在尝试做一个简单的程序来打印附加他们订单的玩家列表(仅用于学习目的).

Right now, I am trying to do a simple program that prints a list of players appending their order(for learning purposes only).

let res : String = pl.name.chars().enumerate().fold(String::new(),|res,(i,ch)| -> String {
    res+=format!("{} {}\n",i.to_string(),ch.to_string());
});

println!("{}", res);

这是我的想法,我知道我可以只使用 for 循环,但目标是了解不同的 Iterator 函数.

This is my idea, I know I could just use a for loop but the objective is to understand the different Iterator functions.

所以,我的问题是字符串连接不起作用.

So, my problem is that the String concatenation does not work.

   Compiling prueba2 v0.1.0 (file:///home/pancho111203/projects/prueba2)
src/main.rs:27:13: 27:16 error: binary assignment operation `+=` cannot be applied to types `collections::string::String` and `collections::string::String` [E0368]
src/main.rs:27             res+=format!("{} {}\n",i.to_string(),ch.to_string());
                           ^~~
error: aborting due to previous error
Could not compile `prueba2`.

我尝试使用 &str 但无法从 ich 值创建它们.

I tried using &str but it is not possible to create them from i and ch values.

推荐答案

首先,在 Rust 中 x += y 是不可重载的,所以 += 操作符不会适用于除基本数字类型之外的任何内容.然而,即使它适用于字符串,它也等价于 x = x + y,如下所示:

First, in Rust x += y is not overloadable, so += operator won't work for anything except basic numeric types. However, even if it worked for strings, it would be equivalent to x = x + y, like in the following:

res = res + format!("{} {}\n",i.to_string(),ch.to_string())

即使类型系统允许这样做(不是因为 String + String 在 Rust 中没有定义重载"),这仍然不是 fold() 操作.你想要这个:

Even if this were allowed by the type system (it is not because String + String "overload" is not defined in Rust), this is still not how fold() operates. You want this:

res + &format!("{} {}\n", i, ch)

或者,作为一个可编译的例子,

or, as a compilable example,

fn main(){
    let x = "hello";
    let res : String = x.chars().enumerate().fold(String::new(), |res, (i, ch)| {
        res + &format!("{} {}\n", i, ch)
    });

    println!("{}", res);
}

当你执行折叠时,你不重新分配累加器变量,你需要返回新值以便在下一次迭代中使用,这正是res + format!(...) 做.

When you perform a fold, you don't reassign the accumulator variable, you need to return the new value for it to be used on the next iteration, and this is exactly what res + format!(...) do.

请注意,我删除了 to_string() 调用,因为它们完全没有必要——事实上,x.to_string() 等效于 format!("{}", x),所以你只在这里执行不必要的分配.

Note that I've removed to_string() invocations because they are completely unnecessary - in fact, x.to_string() is equivalent to format!("{}", x), so you only perform unnecessary allocations here.

此外,我通过引用获取 format!() 结果:&format!(...).这是必要的,因为 + 字符串的重载"是为 String + &str 类型定义的,所以你需要从 String 转换(format!() 的结果)到 &str,这可以通过在这里使用 & 来完成(因为 deref强制).

Additionally, I'm taking format!() result by reference: &format!(...). This is necessary because + "overload" for strings is defined for String + &str pair of types, so you need to convert from String (the result of format!()) to &str, and this can be done simply by using & here (because of deref coercion).

事实上,以下方法会更有效:

In fact, the following would be more efficient:

use std::fmt::Write;

fn main(){
    let x = "hello";
    let res: String = x.chars().enumerate().fold(String::new(), |mut res, (i, ch)| {
        write!(&mut res, "{} {}\n", i, ch).unwrap();
        res
    });

    println!("{}", res);
}

可以更习惯地写成

use std::fmt::Write;

fn main(){
    let x = "hello";

    let mut res = String::new(); 
    for (i, ch) in x.chars().enumerate() {
        write!(&mut res, "{} {}\n", i, ch).unwrap();
    }

    println!("{}", res);
}

(在 playpen 上试试)

这种方式不会创建额外的分配(即来自 format!() 的新字符串).我们只是用新数据填充字符串,例如,与 Java 中 StringBuilder 的工作方式非常相似.use std::fmt::Write 这里需要允许在 &mut String 上调用 write!().

This way no extra allocations (i.e. new strings from format!()) are created. We just fill the string with the new data, very similar, for example, to how StringBuilder in Java works. use std::fmt::Write here is needed to allow calling write!() on &mut String.

我还建议阅读官方 Rust 书中的关于字符串的章节(以及这本书作为如果您是 Rust 的新手,则是一个整体).它解释了 String&str 是什么,它们有何不同以及如何有效地使用它们.

I would also suggest reading the chapter on strings in the official Rust book (and the book as a whole if you're new to Rust). It explains what String and &str are, how they are different and how to work with them efficiently.

这篇关于Rust 字符串连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆