Как проверить, содержит ли строка подстроку в Rust?
Основное решение: метод contains()
Да, ваш подход с методом contains() абсолютно правильный! В Rust есть метод contains() для строк, который работает как для String, так и для &str. Проблема в вашем коде не в самом методе, а в том, как вы его вызвали. Давайте исправим:
fn main() {
let text = String::from("Привет, мир!");
let search = "мир";
if text.contains(search) {
println!("Найдено!");
} else {
println!("Не найдено");
}
}
Этот код будет работать и выведет "Найдено!". Метод contains() определён в трейте StrExt и доступен для всех строковых типов. Он принимает аргумент, реализующий трейт Pattern, куда входят &str, char, замыкания и даже другие строки.
Разница между String и &str
String — это владеемая, изменяемая строка в куче. &str — это ссылка на строковый срез, неизменяемый вид на часть строки. Оба поддерживают contains(). Если у вас String, вы можете вызывать метод напрямую, как в примере выше. Если у вас &str, тоже работает:
let text: &str = "Привет, мир!";
if text.contains("мир") {
println!("Найдено!");
}
Поиск с учётом регистра и без
Стандартный contains() чувствителен к регистру. Для поиска без учёта регистра используйте метод to_lowercase() (или to_uppercase()) для обеих строк:
let text = String::from("Привет, Мир!");
let search = "мир";
if text.to_lowercase().contains(&search.to_lowercase()) {
println!("Найдено (без учёта регистра)!");
}
Обратите внимание: метод to_lowercase() возвращает новую String, поэтому при частых вызовах это может быть неэффективно. Для однократной проверки это нормально.
Дополнительные методы для работы с подстроками
find()— возвращаетOption<usize>с индексом первого вхождения подстроки:
if let Some(pos) = text.find("мир") {
println!("Найдено на позиции {}", pos);
}
matches()— возвращает итератор по всем вхождениям (для подсчёта или обработки):
let count = text.matches("мир").count();
println!("Количество вхождений: {}", count);
starts_with()иends_with()— проверяют начало/конец строки:
if text.starts_with("Привет") {
println!("Строка начинается с 'Привет'");
}
Важное замечание про UTF-8
Rust строки — это UTF-8, поэтому поиск подстроки работает корректно с многобайтовыми символами (русскими, китайскими и т.д.). Однако методы вроде find() возвращают байтовый индекс, а не символьный. Если вам нужна работа с символами (char), используйте итератор .chars():
for (i, c) in text.chars().enumerate() {
if c == 'м' {
println!("Символ 'м' на позиции {}", i);
}
}
Производительность
Метод contains() использует эффективный алгоритм поиска (двухсторонний, на основе алгоритма Two-Way), который работает за O(n+m) в худшем случае. Для большинства задач этого более чем достаточно. Если вам нужен очень быстрый поиск с большими строками, рассмотрите крейт aho-corasick для одновременного поиска множества подстрок.
Альтернативный подход: использование регулярных выражений
Если вам нужен более гибкий поиск (например, с шаблонами, повторениями, границами слов), используйте крейт regex. Добавьте его в Cargo.toml:
[dependencies]
regex = "1"
Пример использования:
use regex::Regex;
fn main() {
let text = "Привет, мир! Мир прекрасен.";
let re = Regex::new(r"\bмир\b").unwrap(); // \b - граница слова
if re.is_match(text) {
println!("Найдено слово 'мир' целиком");
}
// Поиск без учёта регистра
let re_case = Regex::new(r"(?i)мир").unwrap();
if re_case.is_match(text) {
println!("Найдено 'мир' (без учёта регистра)");
}
}
Когда использовать regex вместо contains?
- Когда нужен поиск по шаблону (например, все слова из 4 букв)
- Когда нужно игнорировать регистр без создания новых строк
- Когда нужна замена подстрок с шаблонами
Недостаток: крейт regex добавляет зависимость и увеличивает размер бинарника. Для простой проверки на наличие подстроки лучше использовать встроенный contains().
Ещё один вариант: итераторы и замыкания
Если вам нужно проверить наличие любого символа из набора, используйте any():
let text = "Привет, мир!";
let chars_to_find = ['м', 'и', 'р'];
if chars_to_find.iter().any(|&c| text.contains(c)) {
println!("Строка содержит хотя бы один из указанных символов");
}
Этот подход полезен для проверки на наличие специальных символов или букв.
Ответов пока нет.
Войдите чтобы оставить ответ