LoginSignup
3
0

More than 3 years have passed since last update.

【Java】多重forループを一重にする方法

Last updated at Posted at 2020-01-19

ネタです

はじめに

Javaに限らず,プログラムを書いていると何重ものforループを書かなければならない時が発生します.

例. int型三次元配列の全ての要素を1にしたい.

final int n = 10;
final int[][][] cube = new int[n][n][n];

for (int i = 0; i < n; i++) {
  for (int j = 0; j < n; j++) {
    for (int k = 0; k < n; k++) {
      cube[i][j][k] = 1;
    }
  }
}

しかし,このようなループはネストが深くなったり行数が無駄に増えるため,プログラムの保守性が悪化する原因となります.
そこで,多重forループを一重にする方法を考えます.

forループの構文

問題を解決するために,まずはforループの構文を確認して行きます.
Eclipse JDTによると,for文は以下のような構成になっています

for (
[ ForInit ];
[ Expression ] ;
[ ForUpdate ] )
Statement

また,ForInitとForUpdateは以下のように定義されています.

ForInit:
Expression { , Expression }
ForUpdate:
Expression { , Expression }

ForInitForUpdateは複数の式を指定できるので,ForInitに多重forループで必要となるそれぞれの変数の宣言をForUpdateで変数の更新を書くことができそうです.

やってみた

それでは実際に一重のforループにしていきます.

初期化式

先ほどの例だと,必要な変数はi,j,kの三つなので,初期化式は

int i = 0, j = 0, k = 0

で大丈夫そうです.

条件式

次に(終了)条件式ですが,今回の場合はj,kの値に関係なく,一番外側のループを制御するiについて

i < n

と書くことができます.

更新式

最後に更新式について考えていきます.
ループの内側を制御する変数から順番(k -> j -> i)に考えていきます.
まずkについてですが,ループの度にインクリメントし,なおかつkの値がnになるタイミングで0になればよいので

k = (k + 1) % n

と書けます.

次にjについてですが,jの更新のタイミングはkが0になったタイミングであり,それ以外では値は変わらないため

j = k == 0 ? (j + 1) % n : j

となります.

最後にiですが,更新のタイミングはk == 0 && j == 0なので

i = j == 0 && k == 0 ? i + 1 : i

です.

結果

これまでの結果を統合すると以下のように書き換えられます.

final int n = 10;
final int[][][] cube = new int[n][n][n];

for (int i = 0, j = 0, k = 0; i < n; k = (k + 1) % n, j = k == 0 ? (j + 1) % n : j, i = j == 0 && k == 0 ? i + 1 : i) {
  cube[i][j][k] = 1;
}

最初の三重ループのコードに比べるとネストが減り,すっきりした印象を受けたのではないでしょうか?

おわりに

今回は多重forループを一重ループに変換する方法を紹介しました.
ぜひこれを参考にしてコードの可読性を高めてください!

3
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0