Как я могу преобразовать вектор строк в Rust с помощью карты, а затем соединить строки с помощью Flat_map в одну строку?

Я делаю второй уровень шорохов для главы об итераторе.

Я нашел следующее решение для шага 3, и теперь я хотел бы объединить карты и Flat_map.

// Step 3.
// Apply the `capitalize_first` function again to a slice of string slices.
// Return a single string.
// ["hello", " ", "world"] -> "Hello World"
pub fn capitalize_words_string(words: &[&str]) -> String {
    let capitalized: Vec<String> = words.iter().map(|word| capitalize_first(&word)).collect();
    capitalized.iter().flat_map(|s| s.chars()).collect()
}

Однако при таком наивном подходе...

words.iter().map(|w| capitalize_first(w)).flat_map(|s| s.char_indices()).collect()

Я получаю эти ошибки компилятора, которые я не понимаю:

36   |     words.iter().map(|w| capitalize_first(w)).flat_map(|s| s.char_indices()).collect()
     |                                                                              ^^^^^^^ value of type `String` cannot be built from `std::iter::Iterator<Item=(usize, char)>`
36   |     words.iter().map(|w| capitalize_first(w)).flat_map(|s| s.char_indices()).collect()
     |     ----- ------ ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Iterator::Item` changed to `(usize, char)` here
     |     |     |      |
     |     |     |      `Iterator::Item` changed to `String` here
     |     |     `Iterator::Item` is `&&str` here
     |     this expression has type `&[&str]`

Я смущен вашим замешательством. chars() выдаёт chars, а char_indices() выдаёт индексированные символы, т.е. (usize, char). Это не то же самое. Собирать char можно только в String. Так что, если вам нужен индекс, вам нужно дополнительно .map(|(i, c)| c) избавиться от него, прежде чем .collect() использовать

vallentin 19.03.2024 19:00

Также вы можете собрать итератор строк прямо в строку. Не нужно превращать их в персонажей.

drewtato 19.03.2024 19:22

@drewtato, да, наверное, я не увидел здесь очевидного -.-

Philipp A. 20.03.2024 09:39

@vallentin, поэтому меня смутило то, что это работало в моем первоначальном решении, где я сначала собирал результат карты, а затем снова превращал его в итератор с iter, который будет использоваться flat_map. Но тогда я не был уверен, почему нельзя просто удалить collect и iter и объединить строки.

Philipp A. 20.03.2024 09:43
Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
0
4
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вам действительно нужно конкретно использовать flat_map? Если нет, то это будет сделано так:

fn capitalize_words_strings(words: &[&str]) -> String {
    words.iter()
        .map(|word| capitalize_first(word))
        .collect()
}

Если вам действительно нужно использовать flat_map, вы можете просто добавить «нуп» flat_map, выполнив std::iter::once().

fn capitalize_words_strings(words: &[&str]) -> String {
    words.iter()
        .map(|word| capitalize_first(word))
        .flat_map(|word| std::iter::once(word))
        .collect()
}

Другие вопросы по теме