08 配列(2次元)

1次元配列は「1列に並んだ箱」。では表(テーブル)のようなデータはどう持つ?

クラスの生徒30人が、5教科のテストを受けた結果を管理したいとします。 1次元配列では「1人の5教科分」か「1教科の30人分」しか一度に持てません。 2次元配列を使えば、「行=生徒、列=教科」という表の形でまとめて管理できます。

スプレッドシートや成績表、地図データ、画像データ(ピクセルの集まり)など、 現実世界には「縦×横」の構造を持つデータが無数にあります。 2次元配列はそれを表現するための基本的な道具です。

1. 1次元配列との違い

1次元配列(1行) [1] 10 [2] 20 [3] 30 [4] 40 アクセス:a[2] → 20 2次元配列(行×列) 1行目→ 2行目→ 1列 2列 3列 1 2 3 4 5 6 アクセス:a[2, 3] → 6 1次元: a[要素番号]    例:a[3] 2次元: a[行番号, 列番号] 例:a[2, 3] ← 最後の番号が列(1次元方向)
要素番号の読み方:2次元配列では a[行, 列] の順です。
迷ったときは「最後の番号が1次元方向(横・列)」と覚えておきましょう。

2. 宣言と初期化

整数型の2次元配列: data ← {{1, 2, 3}, {4, 5, 6}}

内側の {} が各行のデータを表します。上記は2行3列の配列です。

列1 列2 列3 行1→ [1, 1] 1 [1, 2] 2 [1, 3] 3 行2→ [2, 1] 4 [2, 2] 5 [2, 3] 6 data[2, 3] → 2行3列目 → 6 / data[1, 2] → 1行2列目 → 2

3. 2重ループで全要素を処理する

2次元配列を全て処理するには、for文を2重にネストして使います。 外側のループで行を、内側のループで列を順に処理するのが基本パターンです。

外側ループ(行):i を 1 から 行数 まで 内側ループ(列):j を 1 から 列数 まで → score[i, j] を処理
整数型の2次元配列: score ← {{70, 80}, {60, 90}, {85, 75}}
整数型: i, j

// 3人×2教科の点数を全て出力
for ( i を 1 から 3 まで 1 ずつ増やす )      // 行(生徒)
    for ( j を 1 から 2 まで 1 ずつ増やす )  // 列(教科)
        score[i, j] を出力
    endfor
endfor
// 出力:70 80 60 90 85 75

全要素の合計を求める例

整数型の2次元配列: score ← {{70, 80}, {60, 90}, {85, 75}}
整数型: i, j
整数型: total ← 0

for ( i を 1 から 3 まで 1 ずつ増やす )
    for ( j を 1 から 2 まで 1 ずつ増やす )
        total ← total + score[i, j]
    endfor
endfor

total を出力   // 出力:460
2重ループの読み方:
i=1 のとき、j が 1→2 と動く(1行目の全列を処理)
i=2 のとき、j が 1→2 と動く(2行目の全列を処理)
i=3 のとき、j が 1→2 と動く(3行目の全列を処理)
合計6回の処理が行われます。

4. 実用的な例:各行の合計

「生徒ごとの合計点」を求めるには、行ループの外に合計変数を置きます。

整数型の2次元配列: score ← {{70, 80}, {60, 90}, {85, 75}}
整数型: i, j
整数型: rowTotal

for ( i を 1 から 3 まで 1 ずつ増やす )
    rowTotal ← 0                              // 行ごとにリセット
    for ( j を 1 から 2 まで 1 ずつ増やす )
        rowTotal ← rowTotal + score[i, j]
    endfor
    rowTotal を出力   // 1行目:150、2行目:150、3行目:160
endfor
rowTotal ← 0 のリセット位置に注目。
内側ループの外・外側ループの内側に置くことで、行が変わるたびにリセットされます。 リセット位置を誤るのは典型的なバグです。

5. 理解度チェック問題

問題08-1

次の配列の定義において data[2, 3] の値はどれか。

整数型の2次元配列: data ← {{1, 2, 3}, {4, 5, 6}}
解説を表示 正解:エ
data[2, 3] は2行3列目。2行目は {4, 5, 6} なので3列目は 6。

問題08-2

次のコードを実行したとき sum の値はいくつになるか。

整数型の2次元配列: table ← {{1, 2}, {3, 4}}
整数型: i
整数型: sum ← 0

for ( i を 1 から 2 まで 1 ずつ増やす )
    sum ← sum + table[i, 1]
endfor
解説を表示 正解:ア
table[1, 1] = 1、table[2, 1] = 3。1列目の合計 → 1 + 3 = 4。

問題08-3

次のコードを実行したとき total の値はいくつになるか。

整数型の2次元配列: mat ← {{1, 2, 3}, {4, 5, 6}}
整数型: i, j
整数型: total ← 0

for ( i を 1 から 2 まで 1 ずつ増やす )
    for ( j を 1 から 3 まで 1 ずつ増やす )
        total ← total + mat[i, j]
    endfor
endfor
解説を表示 正解:ウ
全要素の合計:1+2+3+4+5+6 = 21。2重ループで全6要素を順に加算します。

問題08-4 空欄補充

次のコードは2行3列の2次元配列の全要素を出力するプログラムである。空欄 [ A ][ B ] の組み合わせとして正しいものを選びなさい。

整数型の2次元配列: data ← {{10, 20, 30}, {40, 50, 60}}
整数型: i, j

for ( i を 1 から [ A ] まで 1 ずつ増やす )
    for ( j を 1 から [ B ] まで 1 ずつ増やす )
        data[i, j] を出力
    endfor
endfor
解説を表示 正解:イ
外側ループは行数(2行)、内側ループは列数(3列)。
A=行数=2、B=列数=3。外側と内側を逆にすると存在しない要素にアクセスします。

問題08-5

次のコードを実行すると mat[1, 2] と mat[2, 1] の値はどうなるか。

整数型の2次元配列: mat ← {{1, 2}, {3, 4}}
整数型: tmp

tmp      ← mat[1, 2]
mat[1, 2] ← mat[2, 1]
mat[2, 1] ← tmp
解説を表示 正解:ウ
tmp=2 → mat[1,2]=3 → mat[2,1]=2 の順に処理。対称位置の値を入れ替えています。