Циклы Loops

1. Стандартный цикл for

Синтаксис: for(инициализация; условие; итератор) { тело цикла }

1: Простая конкатенация строк

void main() {
  var message = StringBuffer('welcome to FoxDevelop.com');
  for (var i = 0; i < 5; i++) {
    message.write('!');
  }
  print(message); // welcome to FoxDevelop.com!!!!!
}Code language: Dart (dart)

Цикл выполняется от 0 до 5 (число 5 не включается), переменная i принимает значения от 0 до 4, всего 5 итераций. На каждом шаге в конец строки добавляется восклицательный знак.

1-я итерация: welcome to FoxDevelop.com!

2-я итерация: welcome to FoxDevelop.com!!

5-я итерация: welcome to FoxDevelop.com!!!!!

Особенность: замыкание захватывает отдельный индекс (важное отличие от JavaScript)

В Dart на каждую итерацию цикла создаётся независимая переменная i, поэтому не возникает ошибки JS, когда все колбэки выводят одно значение 2.

void main() {
  var callbacks = [];
  for (var i = 0; i < 2; i++) {
    callbacks.add(() => print(i));
  }
  for (final c in callbacks) {
    c();
  }
}
// Вывод
// 0
// 1
Code language: Dart (dart)

2. Цикл for-in для обхода итерируемых объектов List/Set

Подходит для случаев, когда нужны только значения элементов, без индексов.

Базовая запись

class Candidate {
  void interview() => print("Собеседование завершено");
}

void main() {
  var candidates = [Candidate(), Candidate()];
  for (var candidate in candidates) {
    candidate.interview();
  }
}Code language: Dart (dart)

Обходит список candidates, записывает каждый элемент в переменную candidate и вызывает метод interview(). После обработки одного элемента итератор автоматически переходит к следующему.

Продвинутый вариант

for-in с деструктуризацией объектного паттерна (Dart 3+)

class Candidate {
  final String name;
  final int yearsExperience;
  Candidate({required this.name, required this.yearsExperience});
}

void main() {
  var candidates = [
    Candidate(name: "Lily", yearsExperience: 6),
    Candidate(name: "Tom", yearsExperience: 3),
  ];

  // Прямая деструктуризация полей объекта по паттерну
  for (final Candidate(:name, :yearsExperience) in candidates) {
    print('$name имеет $yearsExperience лет рабочего стажа');
  }
}
Code language: Dart (dart)

В сочетании с ранее рассмотренной деструктуризацией автоматически извлекает два свойства объекта в переменные name и yearsExperience, которые можно использовать внутри тела цикла.

3. Метод обхода Iterable.forEach ()

Встроенный функциональный обход коллекций, принимает колбэк для обработки каждого элемента.

void main() {
  var collection = [1, 2, 3];
  collection.forEach(print);
  // Вывод 1 2 3
}Code language: Dart (dart)

forEach — нативный метод Dart, доступный для любых итерируемых коллекций.

4. while / do-while

1. while

Сначала проверяет условие, потом выполняет тело цикла — блок может не выполниться ни разу. Работает аналогично C, C++, Java, C# и другим языкам.

bool isDone() => false;
void doSomething() => print("Выполнить задачу");

void main() {
  while (!isDone()) {
    doSomething();
    break;
  }
}Code language: Dart (dart)

Сначала вычисляется выражение !isDone(): функция возвращает false, инверсия даёт true, поэтому выполняется внутренний блок:

doSomething();
break;

При встрече оператора break весь цикл немедленно завершается, управление переходит к коду после блока while. Если бы isDone() возвращал true, первая проверка не пройдёт и внутренний код не выполнится ни разу.

2. do-while

Сначала выполняет тело цикла один раз, потом проверяет условие — гарантируется минимум одно выполнение.

bool atEndOfPage() => true;
void printLine() => print("Вывести одну строку");

void main() {
  do {
    printLine();
  } while (!atEndOfPage());
}
Code language: Dart (dart)

Независимо от того, истинно или ложно условие после while, код внутри do {} обязательно выполнится один раз.

5. break / continue

break

Мгновенно завершает весь цикл, переходя к коду после него; оставшиеся инструкции внутри тела цикла не выполняются.

bool shutDownRequested() => true;
void processIncomingRequests() => print("Обработать запросы");

void main() {
  while (true) {
    if (shutDownRequested()) break;
    processIncomingRequests();
  }
  print("Цикл завершён");
}
Code language: Dart (dart)

continue

Пропускает все оставшиеся инструкции текущей итерации и сразу переходит к следующему шагу цикла.

Традиционная запись с for
class Candidate {
  final int yearsExperience;
  Candidate(this.yearsExperience);
  void interview() => print("Провести собеседование");
}

void main() {
  var candidates = [Candidate(3), Candidate(6)];
  for (int i = 0; i < candidates.length; i++) {
    var candidate = candidates[i];
    if (candidate.yearsExperience < 5) {
      continue; // Кандидатам со стажем менее 5 лет собеседование пропускаем
    }
    candidate.interview();
  }
}
Code language: Dart (dart)
Функциональная альтернатива (без continue)
void main() {
  var candidates = [Candidate(3), Candidate(6)];
  candidates
      .where((c) => c.yearsExperience >= 5)
      .forEach((c) => c.interview());
}
Code language: Dart (dart)

6. Метки Label для управления вложенными циклами

Синтаксис: написать ИмяМетки: перед циклом, использовать вместе с break ИмяМетки / continue ИмяМетки

Назначение: при многоуровневой вложенности циклов позволяет сразу выйти из внешнего цикла или пропустить его шаг, а не только внутреннего.

1. break + метка label

Полный выход из двух вложенных циклов

void main() {
  outerLoop:
  for (var i = 1; i <= 3; i++) {
    for (var j = 1; j <= 3; j++) {
      print('i = $i, j = $j');
      if (i == 2 && j == 2) {
        break outerLoop; // Сразу завершить внешний цикл с меткой outerLoop
      }
    }
  }
  print('outerLoop exited');
}
Code language: Dart (dart)

Вывод:

i = 1, j = 1
i = 1, j = 2
i = 1, j = 3
i = 2, j = 1
i = 2, j = 2
outerLoop exited
Code language: Dart (dart)

2. continue + метка label

Переход сразу к следующей итерации внешнего цикла

void main() {
  outerLoop:
  for (var i = 1; i <= 3; i++) {
    for (var j = 1; j <= 3; j++) {
      if (i == 2 && j == 2) {
        continue outerLoop; // Пропустить все оставшиеся j для i=2, перейти сразу к i=3
      }
      print('i = $i, j = $j');
    }
  }
}
Code language: Dart (dart)

Вывод:

i = 1, j = 1
i = 1, j = 2
i = 1, j = 3
i = 2, j = 1
i = 3, j = 1
i = 3, j = 2
i = 3, j = 3

Пример while+break+label

void main() {
  var i = 1;
  outerLoop:
  while (i <= 3) {
    var j = 1;
    while (j <= 3) {
      print('i = $i, j = $j');
      if (i == 2 && j == 2) {
        break outerLoop;
      }
      j++;
    }
    i++;
  }
  print('outerLoop exited');
}
Code language: PHP (php)

Результат выполнения

D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
i = 1, j = 1
i = 1, j = 2
i = 1, j = 3
i = 2, j = 1
i = 2, j = 2
outerLoop exited

Этот механизм работает аналогично оператору goto других языков программирования.

Циклы Loops

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *