一、標準 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)
二、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メソッドを呼び出します。1要素処理後は自動で次の要素へ進みます。
応用
for-in とオブジェクトパターン分解(Dart3以降)
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変数に取り出し、ループ内で使用できます。
三、Iterable.forEach () 走査メソッド
コレクション標準の関数型走査メソッド。コールバックを渡して各要素を処理します。
void main() {
var collection = [1, 2, 3];
collection.forEach(print);
// 出力 1 2 3
}Code language: Dart (dart)
forEachはDart標準メソッドで、すべての反復可能コレクションから呼び出せます。
四、while /do-while
1. while
条件判定を先に行ってから本体を実行するため、1回も実行されない場合があります。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
本体を必ず1回実行した後に条件判定を行うため、最低1回は処理が走ります。
bool atEndOfPage() => true;
void printLine() => print("1行出力");
void main() {
do {
printLine();
} while (!atEndOfPage());
}
Code language: Dart (dart)
後ろのwhile条件がtrue/falseどちらでも、do {}内のコードは必ず1回実行されます。
五、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)
六、ラベル Label による入れ子ループ制御
文法:ラベル名: をループ先頭に記述し、break ラベル / continue ラベル と組み合わせて使用
用途:多重入れ子ループ時、内側だけでなく外側ループを直接脱出・スキップできる
1. break + label
2重ループを一気に脱出
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; // i=2の残りjを全スキップ、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