Как сделать обратный цикл for в Rust? (реверсивный порядок итерации)
Правильный реверсивный цикл в Rust: используем .rev() и RangeInclusive
В Rust диапазоны (Range) по умолчанию идут только в возрастающем порядке. Выражение 10..0 создаёт пустой диапазон, потому что начальное значение больше конечного. Это особенность языка: итерация идёт от start до end, но не включает end, и если start >= end, то итераций не будет.
Для обратного цикла нужно использовать метод .rev() в сочетании с правильным диапазоном. Вот правильное решение вашей задачи (вывести числа от 10 до 1 включительно):
for i in (1..=10).rev() {
println!("{}", i);
}
// Вывод: 10, 9, 8, 7, 6, 5, 4, 3, 2, 1
Разбор:
1..=10— это RangeInclusive. Три точки с равенством..=создают диапазон, который включает оба конца (1 и 10)..rev()— это метод трейтаIterator, который переворачивает порядок итерации. Он возвращает новый итератор, идущий в обратном порядке.- Результат: итерация идёт от 10 вниз до 1.
Если вам нужно от 10 до 0 (включительно), замените на (0..=10).rev().
Почему не работает 10..0?
Потому что 10..0 — это Range (открытый диапазон, не включающий конец). В Rust Range реализует итератор, который проверяет условие: start < end. Если это не так, итератор сразу возвращает None. Поэтому цикл не выполняется ни разу.
Альтернативный способ: явный while
Если по какой-то причине вы не хотите использовать .rev(), можно сделать цикл через while:
let mut i = 10;
while i >= 1 {
println!("{}", i);
i -= 1;
}
Но это менее идиоматично для Rust. Использование итераторов (for + .rev()) считается лучшей практикой, так как:
- Код короче и понятнее.
- Меньше шансов ошибиться с границами.
- Итераторы в Rust оптимизированы и часто не уступают по производительности ручным циклам.
Важный нюанс: производительность
Метод .rev() не создаёт копию данных и не тратит лишнюю память. Он просто переключает направление итератора. Компилятор Rust (LLVM) часто оптимизирует такой код до простого счётчика, как если бы вы написали цикл while вручную. Так что не бойтесь использовать .rev().
Итог: для обратного цикла в Rust всегда используйте (start..=end).rev(). Это просто, безопасно и эффективно.
Использование итератора по вектору или слайсу в обратном порядке
Если вам нужно перебрать элементы коллекции (например, вектора) в обратном порядке, можно использовать метод .iter().rev() или .into_iter().rev():
let numbers = vec![1, 2, 3, 4, 5];
for &num in numbers.iter().rev() {
println!("{}", num);
}
// Вывод: 5, 4, 3, 2, 1
Для изменения самой коллекции используйте .reverse() (мутирующий метод) или .into_iter().rev() для потребления владения:
let mut numbers = vec![1, 2, 3, 4, 5];
numbers.reverse();
for num in &numbers {
println!("{}", num);
}
// Вывод: 5, 4, 3, 2, 1
Также можно использовать .iter().rev() для слайсов (&[T]) и массивов. Это особенно удобно, когда у вас уже есть коллекция, а не числовой диапазон.