let mut item = vec!["2", "3", "5"];
I want to concatenate the first and second index of this vector and replace with the value of zero index.
item[0] = item[0] + item[1];
But due to the type of vector elements being &str
and the result I'm getting after concatenation is String
, Rust is not letting me update the value of vector.
One way to get to the result is through Compiler Driven Development.
Starting with:
fn main() {
let mut item = vec!["2","3","5"];
let first_item = &(item[0].to_owned() + item[1]);
item[0] = item[0] + item[1];
println!("item {:?}", item);
}
We have:
error[E0369]: binary operation `+` cannot be applied to type `&str`
--> src/main.rs:6:22
|
6 | item[0] = item[0] + item[1];
| ------- ^ ------- &str
| | |
| | `+` cannot be used to concatenate two `&str` strings
| &str
|
help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left
|
6 | item[0] = item[0].to_owned() + item[1];
| ^^^^^^^^^^^^^^^^^^
Following the compiler suggestion:
item[0] = item[0].to_owned() + item[1];
Now we get:
|
6 | item[0] = item[0].to_owned() + item[1];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| expected `&str`, found struct `std::string::String`
| help: consider borrowing here: `&(item[0].to_owned() + item[1])`
Then applying again the suggestion:
|
6 | item[0] = &(item[0].to_owned() + item[1]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
7 |
8 | println!("item {:?}", item);
| ---- borrow later used here
Now the problem is related to lifetime scopes, following the compiler suggestion this is the final version:
fn main() {
let mut item = vec!["2","3","5"];
let first_item = &(item[0].to_owned() + item[1]);
item[0] = first_item;
println!("item {:?}", item);
}
The compiler has driven to a solution, but in every case you have to carefully consider if this is a solution that meets the requirements of your application. In this case you must pay attention to lifetime scopes.
Another, more idiomatic solution, as already suggested, could be to use a Vec of String:
let mut item: Vec<String> = vec!["2".to_owned(), "3".to_owned(), "5".to_owned()];
item[0] = format!("{}{}", item[0], item[1]);
Assuming you want to do it in runtime, it is not possible. &str
is non-owning type, one can't concatenate two &str
's into one for the storage they point to may be non-contigious.
You may achieve the goal using String
:
let mut item = vec![String::from("2"), String::from("3"), String::from("5")];
// Vec is not empty and contains more than 1 element, it is safe to unwrap
let (first, rest) = item.split_first_mut().unwrap();
// Append the second element to the end of the first element
first.push_str(rest[0].as_str());
println!("{}", &first); // 23
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.