I am trying to concatenate every element in a slice of &str
s (&[&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`
--> code.rs:2:38
|
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/iterator.rs:1780:19
|
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.
CodePudding user response:
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>()