Как разбить строку (String или &str) на части в Rust?
Основной способ: метод .split() и сбор в коллекцию
В Rust для разбиения строки используется метод .split(), который есть как у &str, так и у String (через авторазыменование). Он возвращает итератор, поэтому чтобы получить вектор или массив, нужно использовать .collect().
let text = "apple,banana,grape";
let parts: Vec<&str> = text.split(',').collect();
println!("{:?}", parts); // ["apple", "banana", "grape"]
Обратите внимание: тип элемента вектора — &str (срез исходной строки). Rust не создаёт новые строки, а просто указывает на куски исходной строки. Это эффективно по памяти.
Разбиение по пробелам и удаление пустых частей
Если нужно разбить по пробельным символам и проигнорировать пустые строки (например, при двойных пробелах), используйте .split_whitespace():
let text = "a b c";
let parts: Vec<&str> = text.split_whitespace().collect();
println!("{:?}", parts); // ["a", "b", "c"]
Метод .split_whitespace() автоматически удаляет пустые результаты.
Разбиение по подстроке (несколько символов)
Если разделитель — не один символ, а целая подстрока, .split() тоже работает:
let data = "one--two--three";
let parts: Vec<&str> = data.split("--").collect();
println!("{:?}", parts); // ["one", "two", "three"]
Ограничение количества частей
Метод .splitn() позволяет указать максимальное количество фрагментов:
let text = "a,b,c,d";
let parts: Vec<&str> = text.splitn(3, ',').collect();
println!("{:?}", parts); // ["a", "b", "c,d"]
Работа с Unicode (кириллица)
Метод .split() работает корректно с любыми Unicode-символами, включая кириллицу:
let text = "яблоко,банан,виноград";
let parts: Vec<&str> = text.split(',').collect();
println!("{:?}", parts); // ["яблоко", "банан", "виноград"]
Разница между String и &str
&str— это срез (ссылка на часть строки). Метод.split()возвращает&strсрезы, которые ссылаются на исходные данные.String— владеющая строка. Если вам нужны новые строки (а не ссылки), используйте.map(|s| s.to_string()):
let text = String::from("a,b,c");
let owned_parts: Vec<String> = text.split(',').map(|s| s.to_string()).collect();
println!("{:?}", owned_parts); // ["a", "b", "c"]
Разбиение строки на символы (графемы)
Если нужно разбить на отдельные символы (с учётом Unicode-графем), используйте .chars():
let text = "привет";
let chars: Vec<char> = text.chars().collect();
println!("{:?}", chars); // ['п', 'р', 'и', 'в', 'е', 'т']
Для работы с графемными кластерами (например, эмодзи) используйте крейт unicode-segmentation.
Важное замечание
Метод .split() возвращает ссылку на исходную строку. Это значит, что исходная строка должна жить дольше, чем полученные срезы. Если это проблема, копируйте в String через .to_string().
Итог
- Для базового разбиения:
text.split(',').collect::<Vec<_>>() - Для пробелов:
text.split_whitespace() - Для ограничения количества:
text.splitn(n, pat) - Для владеющих строк: добавьте
.map(|s| s.to_string())
Альтернативный подход: работа с регулярными выражениями
Если разделитель сложный (например, нужно разбить по запятой, точке с запятой или пробелу одновременно), удобно использовать крейт regex.
Добавьте в Cargo.toml:
[dependencies]
regex = "1"
Пример использования:
use regex::Regex;
fn main() {
let text = "apple; banana,grape orange";
let re = Regex::new(r"[,; ]+").unwrap(); // один или более разделителей
let parts: Vec<&str> = re.split(text).collect();
println!("{:?}", parts); // ["apple", "banana", "grape", "orange"]
}
Разбиение с удалением пустых строк вручную
Если стандартный .split() оставляет пустые строки (например, при разбиении "a,,b" по запятой), их можно отфильтровать:
let text = "a,,b,c";
let parts: Vec<&str> = text.split(',')
.filter(|s| !s.is_empty())
.collect();
println!("{:?}", parts); // ["a", "b", "c"]
Работа с ленивыми итераторами
Если вам не нужна вся коллекция сразу, можно обрабатывать части по одной:
let text = "a,b,c";
for part in text.split(',') {
println!("Part: {}", part);
}
Это позволяет экономить память при работе с большими строками.
Ответов пока нет.
Войдите чтобы оставить ответ