#string #rust #iterator #substring
#строка #Ржавчина #итератор #подстрока
Вопрос:
Многие методы итератора Rust генерируют итераторы, завернутые в итераторы. Одним из таких случаев является skip
метод, который пропускает заданное количество элементов и выдает оставшиеся, завернутые в Skip
структуру, которая реализует Iterator
признак.
Я хотел бы читать файл построчно и иногда пропускать n
первые символы строки. Я полагал, что использование Iterator.skip
сработает, но теперь я застрял, выясняя, как я могу фактически развернуть полученный Chars
итератор, чтобы я мог материализовать оставшийся amp;str
с chars.as_str()
помощью.
Каков идиоматический способ разворачивания итератора в rust? Цепочка вызовов
let line: amp;String = ...;
let remaining = line.chars().skip(n).as_str().trim();
вызывает ошибку
error[E0599]: no method named `as_str` found for struct `std::iter::Skip<std::str::Chars<'_>>` in the current scope
--> src/parser/directive_parsers.rs:367:63
|
367 | let option_val = line.chars().skip(option_val_indent).as_str().trim();
| ^^^^^^ method not found in `std::iter::Skip<std::str::Chars<'_>>`
error: aborting due to previous error
Комментарии:
1.
Skip
это просто итератор по элементам базового итератора, но без первых n элементов. Просто используйте его как итератор. Вложенный итератор в вашей ситуации звучит несвязанно — это потому, что вы выполняете итерацию по строкам, а затем по символам.2.
Skip
является итератором. Вам нужно.collect()
это.3. На самом деле звучит так, как будто вы вообще не хотите выполнять итерацию по символам. Вы, вероятно, просто хотите взять фрагмент строк? Выполняя это с помощью символов, вам нужно будет собрать в a
String
, что кажется ненужным выделением.4. @PeterHall Да, брать фрагменты было бы замечательно, но я заранее не знаю индексов байтов моих символов. Вот почему я был расточителен и имел дело в основном с
Chars
итераторами.5. Это означает, что вы должны обрабатывать все допустимые UTF-8? В зависимости от вашего варианта использования, переход вручную
.char_indices()
может быть значительным улучшением. Тем более, что это экономит вам дополнительное выделение. Однако попахивает преждевременной оптимизацией, сделайте пометку в коде и двигайтесь дальше.
Ответ №1:
Вы можете получить начальный байтовый индекс n-го символа, используя nth()
метод в char_indices()
итераторе строки. Как только у вас будет этот байтовый индекс, вы можете использовать его для получения фрагмента исходной строки:
let line = "This is a line.";
let index = line.char_indices().nth(n).unwrap().0;
let remaining = amp;line[index..];
Ответ №2:
Вместо повторения chars
вы можете использовать char_indices
для нахождения точной точки, в которой нужно взять фрагмент из строки, гарантируя, что вы не будете индексировать середину многобайтового символа. Это позволит сэкономить на выделении для каждой строки в итераторе:
input
.iter()
.map(|line| {
let n = 2; // get n from somewhere?
let (index, _) = line.char_indices().nth(n).unwrap();// better error handling
amp;line[index..]
})