цикли for
for і range
Конструкцію for in можна використовувати для ітерації через Iterator.
Один із найпростіших способів створити ітератор — використати нотацію
діапазону a..b. Це дає значення від a (включно) до b
(виключно) з кроком один.
Давайте напишемо FizzBuzz, використовуючи for замість while.
fn main() {
// `n` will take the values: 1, 2, ..., 100 in each iteration
for n in 1..101 {
if n % 15 == 0 {
println!("fizzbuzz");
} else if n % 3 == 0 {
println!("fizz");
} else if n % 5 == 0 {
println!("buzz");
} else {
println!("{}", n);
}
}
}
Альтернативно, a..=b можна використати для діапазону, який є включним з обох
кінців.
Вище можна записати так:
fn main() {
// `n` will take the values: 1, 2, ..., 100 in each iteration
for n in 1..=100 {
if n % 15 == 0 {
println!("fizzbuzz");
} else if n % 3 == 0 {
println!("fizz");
} else if n % 5 == 0 {
println!("buzz");
} else {
println!("{}", n);
}
}
}
Просто пам’ятайте, що хоча ви можете скомпілювати код, коли a>b, цикл ніколи не виконується.
for i in 10..1{
println!("fizzbuzz");
}
Якщо ви хочете рахувати у зворотному напрямку, вам потрібно використати .rev() замість цього
for i in (1..10).rev(){
println!("fizzbuzz");
}
for і ітератори
Конструкція for in може взаємодіяти з Iterator кількома способами.
Як обговорювалося в розділі про трейт Iterator, за замовчуванням цикл for
застосує функцію into_iter до колекції. Однак це
не єдиний спосіб перетворення колекцій на ітератори.
into_iter, iter і iter_mut усі виконують перетворення колекції
на ітератор різними способами, надаючи різні подання даних
усередині.
iter- Це запозичує кожен елемент колекції через кожну ітерацію. Таким чином, колекція залишається недоторканою і доступною для повторного використання після циклу.
fn main() {
let names = vec!["Bob", "Frank", "Ferris"];
for name in names.iter() {
match name {
&"Ferris" => println!("There is a rustacean among us!"),
// TODO ^ Try deleting the & and matching just "Ferris"
_ => println!("Hello {}", name),
}
}
println!("names: {:?}", names);
}
into_iter- Це споживає колекцію, так що на кожній ітерації надаються точні дані. Щойно колекцію було спожито, вона більше не доступна для повторного використання, оскільки її було ‘переміщено’ всередині циклу.
fn main() {
let names = vec!["Bob", "Frank", "Ferris"];
for name in names.into_iter() {
match name {
"Ferris" => println!("There is a rustacean among us!"),
_ => println!("Hello {}", name),
}
}
// `names` has been 'moved' and can no longer be used.
// Try uncommenting the line below to see the compiler error:
// println!("names: {:?}", names);
}
iter_mut- Це змінно запозичує кожен елемент колекції, дозволяючи змінювати колекцію на місці.
fn main() {
let mut names = vec!["Bob", "Frank", "Ferris"];
for name in names.iter_mut() {
*name = match name {
&mut "Ferris" => "There is a rustacean among us!",
_ => "Hello",
}
}
println!("names: {:?}", names);
}
У наведених вище фрагментах зверніть увагу на тип гілки match, це ключова
різниця в типах ітерації. Різниця в типі, звісно,
передбачає різні дії, які можна виконати.