Я пытаюсь объединить каждый элемент в фрагменте &str
s (&[&str]
) в один принадлежащий String
. Например, я хочу превратить &['Hello', ' world!']
в "Hello world!"
.
Я попытался сделать это, преобразовав срез в итератор, затем сопоставив итератор и преобразовав каждый &str
в собственный String
, затем собрав их все в Vec<String>
и запустив .join("")
, но я продолжаю получать ошибку типа.
Вот мой код:
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"
}
И вот ошибка компилятора, которую я получаю:
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`.
В нем говорится, что я не могу собрать в Vec<String>
, потому что итератор не из String
, но я думал, что преобразовал его в String
с .map(|s| s.to_owned())
.
Как я могу это исправить? Я также новичок в ржавчине, поэтому было бы очень полезно, если бы кто-нибудь мог объяснить, что я сделал неправильно.
into_iter
даст итератор с Item=&&str
. На вашей карте .to_owned()
преобразует это в &str
, что не работает. Есть несколько способов исправить это, вы можете использовать .copied
или .cloned
, чтобы получить &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("")
Или вы можете использовать .to_string()
, чтобы получить String
напрямую:
a.into_iter().map(|s| s.to_string()).collect::<Vec<String>>().join("")
Обратите внимание, что вы также можете просто collect
в String
, когда вам не нужен разделитель напрямую:
a.into_iter().map(|s| s.to_string()).collect::<String>()
fn concat_str(a: &[&str]) -> String {
a.iter()
.cloned()
.collect()
}
Существуют методы join и concat непосредственно на срезе, так что вы можете написать:
fn concat_str(a: &[&str]) -> String {
a.concat()
}
который дает вам желаемый результат
.join("")
->.concat()
.