多次元配列
配列の配列で表形式・木構造のデータを扱う
配列の中に配列を入れて「表」「オブジェクトリスト」「CSV データ」を扱うトピック。実務で扱うデータはほぼこの形なので、ここから「使える PHP」の入口になる。
このトピックで身につくこと
- 表 (行 × 列) のデータを PHP の配列で表現できる
- 行ごと・列ごとの集計ができる
- ユーザー一覧のような「オブジェクトの配列」を作って検索できる
- CSV テキストをパースして配列にできる
- 多次元配列を foreach で走査して処理できる
前提知識の要点
このトピックを始めるのに必要な部分だけをここで圧縮しておく。他のトピックの README を読み返さずに array-multi を単独で開始できる ようにする。
1. 添字配列
$row = [10, 20, 30];
echo $row[0]; // 10
echo count($row); // 32. 連想配列
$user = ['name' => '太郎', 'age' => 20];
echo $user['name']; // 太郎3. foreach の 2 つの形
// 値だけ
foreach ($row as $v) { echo $v . "\n"; }
// キーと値
foreach ($user as $k => $v) {
echo "{$k}: {$v}\n";
}4. for の入れ子
for ($i = 0; $i < 3; $i++) {
for ($j = 0; $j < 3; $j++) {
echo "{$i},{$j} ";
}
echo "\n";
}- 外側の for が 1 回まわるごとに、内側の for が最後まで回る
- このトピックではこの「入れ子」を 配列に対して 行う
5. 標準入力で複数行読む
$n = (int)trim(fgets(STDIN)); // 1 行目: 行数
$lines = [];
for ($i = 0; $i < $n; $i++) {
$lines[] = trim(fgets(STDIN));
}6. 文字列を分割
$parts = explode(",", "tokyo,osaka,nagoya");
// ["tokyo", "osaka", "nagoya"]- CSV を扱う ch11 で使う
ここまで読めば ch01 から始められる。
chapter 一覧
| # | chapter | 内容 | 学習目標 |
|---|---|---|---|
| 1 | ch01-2d-create/ |
2 次元配列を作る | [[1,2],[3,4]] の形で配列を入れ子にできる |
| 2 | ch02-2d-access/ |
要素にアクセス | $grid[行][列] で値を取り出せる |
| 3 | ch03-2d-modify/ |
要素を書き換える | $grid[行][列] = 値 で更新できる |
| 4 | ch04-2d-foreach/ |
入れ子 foreach で全走査 | 二重 foreach で全要素を扱える |
| 5 | ch05-table-print/ |
表形式で整形出力 | 行と列をそろえて表のように表示できる |
| 6 | ch06-row-sum/ |
各行の合計を出力 | 行ごとに合計値を求められる |
| 7 | ch07-col-sum/ |
各列の合計を出力 | 列ごとに合計値を求められる |
| 8 | ch08-assoc-multi/ |
連想配列の中に配列 | 入れ子の連想配列 ($obj['scores'][0]) を扱える |
| 9 | ch09-objects-list/ |
オブジェクトリスト | 連想配列の配列 (ユーザー一覧の形) を作れる |
| 10 | ch10-find-by-key/ |
条件で検索 | キーの値が条件に合う要素を探せる |
| 11 | ch11-csv-to-2d/ |
CSV を 2 次元配列に | explode() で CSV を 2 次元配列にパースできる |
| 12 | ch12-summary/ |
多次元配列の総合演習 | 学生別・科目別の成績データを処理できる |
合計 12 chapter / 16 drill / 所要 約 2.5 時間 程度 (ch12 は少し重め)。
進め方
- 各 chapter の
slide.mdを読む (3〜5 分) drill/配下の問題を順番に解く- 採点:
php scripts/grade.php topics/array-multi/<chapter>/drill/<drill>/
つまづきポイント
| 症状 | 多くの原因 |
|---|---|
Undefined array key 0 で 2 次元目で死ぬ |
$grid[行] が配列か確認していない → is_array($grid[$i]) を確認 |
| 行と列が逆に出る | $grid[列][行] と書いている → 外側の添字が「行」 |
列の合計が 0 のまま |
内側の foreach で外側の合計を加算している → スコープを意識して $colSum[$j] のようにキー指定 |
| CSV をパースして要素数が合わない | 行末に改行や空白が残っている → trim() してから explode() |
| オブジェクトリストで「キーがおかしい」 | 添字配列 ([$user1, $user2]) と連想配列 (['taro' => $user1]) を混同 → 一覧は前者で持つのが基本 |
二重 foreach の as $v が読みにくい |
外側を as $row、内側を as $cell のように 意味のある名前 にする |
関連トピック
| トピック | 関係 |
|---|---|
| function | 多次元配列を引数・戻り値で扱うときに必要 |
| class | オブジェクトリストの代わりにクラスでデータを表現できる |
| exception | CSV パース失敗時のエラーを構造的に扱う |
トピックを並列で参照する全体地図は TOPICS_INDEX.md にある。
案件 (dojo_map.tsv) での参照
topic_slug chapter_dir
array-multi topics/array-multi/ch01-2d-create
array-multi topics/array-multi/ch04-2d-foreach
array-multi topics/array-multi/ch11-csv-to-2d
...
slug array-multi で参照可。06-array-multi / array-multi どちらの path でもアクセスできる (シンボリックリンク)。