Есть ли в стандартной библиотеке Rust функция find
, которая ищет подстроку, начинающуюся с заданного индекса в строке? Так же, как indexOf
в JavaScript.
Как найти в подстроке, начинающейся с определенного индекса в Rust?
comment
Это похоже на Найти строку, начинающуюся с заданного индекса, но я найти ответы там неудовлетворительными, потому что они увязли в конкретном случае ОП.
- person kmdreko   schedule 19.02.2021
Ответы (2)
Вы должны использовать str::find
для подстроки и затем добавьте смещение обратно:
let s = "foobarfoo";
let index: Option<usize> = s[4..].find("foo").map(|i| i + 4);
println!("{:?}", index);
Some(6)
person
kmdreko
schedule
19.02.2021
Хотя это нормально для текста ascii, с этим возникает несколько проблем, если
s
содержит общий юникод, поскольку s[x..]
- это фрагмент, начинающийся с байта x, а не с символа x^th.
- person Michael Anderson; 19.02.2021
@MichaelAnderson Верно, но чтобы избежать этого, это зависит от того, что
4
означает: первые четыре байта? первые четыре скалярных значения Юникода? первые четыре графемы? У всех разные ответы. Если мы нашли 4
, сначала найдя первый b
, то мы уже знаем его юникод-байтовое выравнивание. Также стоит отметить, что String.prototype.indexOf
и std::string::find
дают разные результаты при использовании unicode.
- person kmdreko; 19.02.2021
Все эти вещи могут давать разные ответы, и это нормально. Однако
s[4..]
может запаниковать - обычно это не тот ответ, который вам нужен. Я думаю, что если вы просто относитесь к обоим как к байтам, вы, по крайней мере, избегаете паники.
- person Michael Anderson; 19.02.2021
@MichaelAnderson, я думаю, 4 - это сумма позиции первого появления и длины искомой строки, поэтому она всегда должна быть правильной позицией unicode char. kmdreko, было бы хорошо, если бы вы заменили magic 4 вот такими вычислениями, чтобы было понятно новым пользователям ржавчины.
- person Angelicos Phosphoros; 20.02.2021
Я могу думать о двух способах:
Используйте метод .get()
, чтобы безопасно получить фрагмент строки ASCII, а затем примените к нему .find
.
let s = "foobarfoo";
let res = s.get(4..).and_then(|s| s.find("foo").map(|i| i + 4));
Используйте match_indices
для перебора совпадений и их индексов, а затем find_map
тот, который соответствует первому условию.
let s = "foobarfoo";
let res = s.match_indices("foo").find_map(|(i, _)| (i >= 4).then(|| i));
- Оба метода вернут
Some(6)
. - Если индекс больше или равен длине строки, вы получите
None
.
person
Jason
schedule
19.02.2021