Concatenate a slice of `&str`s into an owned `String`

I am trying to concatenate every element in a slice of &strs (&[&str]) into a single owned String. For example, I want to turn &['Hello', ' world!'] into "Hello world!".

I tried to do this by converting the slice into an iterator, then mapping over the iterator and converting each &str into an owned String, then collect them all into a Vec<String> and running .join(""), but I keep getting a type error.

Here is my code:

fn concat_str(a: &[&str]) -> String {
    a.into_iter().map(|s| s.to_owned()).collect::<Vec<String>>().join("")

fn main() {
    let arr = ["Dog", "Cat", "Bird", "Lion"];

    println!("{}", concat_str(&arr[..3])); // should print "DogCatBird"
    println!("{}", concat_str(&arr[2..])); // should print "BirdLion"
    println!("{}", concat_str(&arr[1..3])); // should print "CatBird"

And here is the compiler error that I am getting:

error[E0277]: a value of type `Vec<String>` cannot be built from an iterator over elements of type `&str`
2    |     a.into_iter().map(|s| s.to_owned()).collect::<Vec<String>>().join("")
     |                                         ^^^^^^^ value of type `Vec<String>` cannot be built from `std::iter::Iterator<Item=&str>`
     = help: the trait `FromIterator<&str>` is not implemented for `Vec<String>`
note: required by a bound in `collect`
    --> /Users/michaelfm1211/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/library/core/src/iter/traits/
1780 |     fn collect<B: FromIterator<Self::Item>>(self) -> B
     |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.

It says that I cannot collect into a Vec<String> because the iterator is not of a String, but I thought that I had converted it to a String with .map(|s| s.to_owned()).

How can I fix this? I am also new to rust, so it would be very helpful is someone could explain what I did wrong.

>Solution :

into_iter will yield an iterator with Item=&&str. In your map, .to_owned() converts that into a &str, which doesn’t work. There are a few ways to fix that, you could use .copied or .cloned to get a &str:

a.into_iter().copied().map(|s| s.to_owned()).collect::<Vec<String>>().join("")
// or
a.into_iter().cloned().map(|s| s.to_owned()).collect::<Vec<String>>().join("")

Or you could use .to_string() to get a String directly:

a.into_iter().map(|s| s.to_string()).collect::<Vec<String>>().join("")

Note, you can also just collect into a String when you don’t want a separator directly:

a.into_iter().map(|s| s.to_string()).collect::<String>()

Leave a Reply