# ch11 — 入力 CSV を 2 次元配列にする

Source: https://php-school.pages.dev/topics/array-multi/ch11-csv-to-2d/
Site: AIと学ぶPHPの学校 (https://php-school.pages.dev)
Lesson: 多次元配列
Level: L2

Reference (official): https://www.php.net/manual/ja/language.types.array.php

## 本文

# ch11 — 入力 CSV を 2 次元配列にする

## 概要

CSV (Comma-Separated Values) は **実務で最もよく出会うデータ形式** の 1 つ。Excel・Google スプレッドシート・DB のエクスポート・ログ・売上データなど、外部から渡されるデータはほぼこの形になる。CSV を PHP で扱う基本は「**1 行ずつ標準入力で受け取り、`explode(",", $line)` でカンマ区切りに分解し、2 次元配列に組み立てる**」というシンプルな流れだ。

組み立ての骨格は `$rows = []; for ($i = 0; $i < $n; $i++) { $line = trim(fgets(STDIN)); $rows[] = explode(",", $line); }`。**1 行読む → カンマで分割 → 2 次元配列に追加** を行数分くり返すだけ。`trim` で末尾の改行を取り除いてから `explode` するのがコツで、これを忘れると最後の要素に `\n` が混ざって数値変換に失敗するなどの **しょっぱい事故** が起きる。要素を数値として扱いたいときは `(int)` などで明示的にキャストする。

2 次元配列に組み上がれば、あとは ch04〜ch07 で扱った **入れ子 foreach / 行合計 / 列合計** の手法がそのまま使える。ドリル 02 では「CSV → 2 次元配列 → 各列の合計」というパイプラインを通して、**ばらばらに見えた章の知識が 1 本の処理として繋がる** ことを体感する。これが「**実務で動く PHP**」の入口で、ここまで来れば自分でレポート集計スクリプトが書けるレベルになる。

## 学習目標

- 標準入力で複数行を受け取り、各行を `explode(",", $line)` で分割できる
- 分割結果を 2 次元配列に組み立てられる
- 組み立てた 2 次元配列に対して、これまでの章 (合計など) を適用できる

## 所要時間

スライド 5 分 + ドリル 2 問 = **20 分**

## ドリル

| no | 内容 |
|---|---|
| 01 | CSV 入力を 2 行 3 列の配列にして表形式で出力 |
| 02 | CSV 入力を 2 次元配列にして各列の合計を出力 |

## 採点

```bash
php scripts/grade.php topics/array-multi/ch11-csv-to-2d/drill/01-parse-csv/
```

## 関連チャプター

- [`ch05-table-print`](../ch05-table-print/) — 組み立てた 2 次元配列を表形式で出力する
- [`ch07-col-sum`](../ch07-col-sum/) — CSV を読み込んで列合計を出す応用 (ドリル 02)
- [`ch12-summary`](../ch12-summary/) — 標準入力 + 2 次元配列の総合演習

## スライド

---
marp: true
theme: dojo
paginate: true
size: 16:9
---

<!--
LLM_CONTEXT:
  Lesson 6 / Chapter 11
  目的: 標準入力の CSV (複数行) を 2 次元配列に組み立て、これまでの章の処理を適用できるようにする
  扱わない: 関数化 (L7) / クラス (L8)
  読み上げ時間目安: 4 分半〜5 分
-->

# CSV を 2 次元配列にする

Lesson 6 / Chapter 11

---

## CSV の形を思い出す

入力例:

```
a,b,c
1,2,3
4,5,6
```

- 1 行 = 1 レコード
- `,` で列を区切る
- これを 2 次元配列にすると `[ ["a","b","c"], ["1","2","3"], ["4","5","6"] ]`

---

## 1 行を分割する `explode`

```php
<?php
$line = "1,2,3";
$cols = explode(",", $line);
print_r($cols);
```

実行結果:

```
Array ( [0] => 1 [1] => 2 [2] => 3 )
```

- `explode(区切り文字, 文字列)` で文字列を配列に分割
- 結果は **全て文字列** になる (数値が必要なら `(int)` で変換)

---

## 入力を 1 行ずつ読みながら配列に追加

```php
<?php
$table = [];
while (($line = fgets(STDIN)) !== false) {
    $line = rtrim($line, "\n");
    if ($line === "") continue;
    $cols = explode(",", $line);
    $table[] = $cols;
}
print_r($table);
```

- `fgets(STDIN)` で 1 行読む (EOF で `false`)
- `$table[] = $cols` で末尾に追加
- これで 2 次元配列の完成

---

## 数値として扱いたいなら型変換

```php
<?php
$table = [];
while (($line = fgets(STDIN)) !== false) {
    $line = rtrim($line, "\n");
    if ($line === "") continue;
    $cols = explode(",", $line);
    $row = [];
    foreach ($cols as $c) {
        $row[] = (int) $c;
    }
    $table[] = $row;
}
```

- 合計や平均を出すなら、文字列のままだと計算がおかしくなる
- `(int)$c` で整数に変換してから追加

---

## 組み立てたら、後はこれまでの章と同じ

```php
// 各行の合計
foreach ($table as $row) {
    echo array_sum($row) . "\n";
}

// 各列の合計
$cols = count($table[0]);
for ($j = 0; $j < $cols; $j++) {
    $sum = 0;
    foreach ($table as $row) {
        $sum += $row[$j];
    }
    echo $sum . "\n";
}
```

- 入力を整え終われば、ch06 / ch07 と同じ処理がそのまま使える

---

## このチャプターでできるようになること

✅ `fgets(STDIN)` で複数行入力を読める
✅ `explode(",", $line)` で 1 行を配列に分割できる
✅ `$table[] = $cols` で 2 次元配列に組み立てられる
✅ 型変換でから合計などの計算に持ち込める

→ ドリルへ
