String Iterators
Отображение части строки
Передавать владельца не нужно, передаём в &str:
let s = String::from("Hello World!");
let word = first_word(&s);
println!("The first word is: {}", word);
}
fn first_word(s: &String) -> &str { // передача строки по ссылке
let word_count = s.as_bytes();
for (i, &item) in word_count.iter().enumerate() {
if item == b' ' {
return &s[..i]; // возврат части строки как &str
}
}
&s[..] // обязательно указать возвращаемое значение, если условие в цикле выше ничего не вернёт (например, строка не содержит пробелов = вернуть всю строку)
‘Проход’ по строке итератором
Можно пройти по строке итератором chars() и его методами взятия N-го символа nth() спереди или nth_back() сзади:
let person_name = String::from("Alice");
println!("The last character of string is: {}", match person_name.chars().nth_back(0) { // ищем 1-ый символ с конца строки
Some(i) => i.to_string(), // если находим - превращаем в строку
None => "Nothing found!".to_string(), // не находим = сообщаем
});
matches() и rmatches(),
Возвращают итератор с теми частями строки, которые совпадают с заданным шаблоном:
let v: Vec<&str> = "abcXXXabcYYYabc".matches("abc").collect();
assert_eq!(v, ["abc", "abc", "abc"]); // вывод слева-направо
let v: Vec<&str> = "1abc2abc3".rmatches(char::is_numeric).collect();
assert_eq!(v, ["3", "2", "1"]); // вывод справа-налево
find() и rfind()
Возвращает Option<байт индекс 1го символа в строке слева-направо>, совпадающий с шаблоном. Либо возвращает None, если символ отсутствует в строке. rfind
fn duplicate_encode2(word: &str) -> String {
let s = String::from(word).to_lowercase();
s.chars()
.map(|c| if s.find(c) == s.rfind(c) { '(' } else { ')' })
.collect() } // если у символа есть дубли => замена на '(',
// иначе на ')'
fn main() {
println!("{}", duplicate_encode("rEcede"));
}Примеры
Повтор части строки n раз
Новый подход использует std::repeat
fn main() {
let repeated = "Repeat".repeat(4);
println!("{}", repeated); // RepeatRepeatRepeatRepeat
}
Старый вариант через итератор - позволяет бесконечно отдавать любое значение (как generic):
use std::iter;
fn main() {
let repeated: String = iter::repeat("Repeat").take(4).collect();
println!("{}", repeated);
}Удаление пробелов в строке String
Use split(' '), filter out empty entries then re-join by space:
s.trim()
.split(' ')
.filter(|s| !s.is_empty())
.collect::<Vec<_>>()
.join(" ")
// Using itertools:
use itertools::Itertools;
s.trim().split(' ').filter(|s| !s.is_empty()).join(" ")
// Using split_whitespace, allocating a vector & string
pub fn trim_whitespace_v1(s: &str) -> String {
let words: Vec<_> = s.split_whitespace().collect();
words.join(" ")
}Озаглавить каждое слово в предложении
В заданной фразе озаглавить каждое слово. Если результат больше 140 символов или пустой, вернуть None:
fn capitalize_first_letter(s: &str) -> Option<String> {
let res = s
.split_whitespace()
.map(capital) // каждое слово передать в функцию capital()
.collect::<Vec<String>>() // собрать в вектор
.join(" "); // потому что вектор можно собрать в string с join()
if res.len() < 141 || !res.is_empty() { // проверка длины
Some(res)
} else { None } }
fn capital(word: &str) -> String {
let mut lword = word.to_ascii_lowercase();
// изменить НА МЕСТЕ - прямо в этой строке (быстрее всего):
lword[0..1].make_ascii_uppercase();
lword // вернуть итоговую строку
}