# 機能設計書：コレクション操作

## 1. 機能概要

### 1.1 機能名
コレクション操作（Collection）

### 1.2 機能説明
配列データをオブジェクト指向で操作するためのラッパークラス。map、filter、reduce などの関数型プログラミングスタイルのメソッドを提供し、データの変換・集計・検索を直感的に行える。LazyCollection による遅延評価もサポート。

### 1.3 関連画面
- なし（全機能で横断的に使用されるユーティリティ）

## 2. 機能詳細

### 2.1 処理フロー

```
[配列データ]
    |
    v
[Collection::make() / collect()]
    |
    v
[Collection インスタンス]
    |
    +-- 変換: map(), pluck(), flatMap()
    +-- 絞り込み: filter(), where(), reject()
    +-- 集計: sum(), avg(), count(), max(), min()
    +-- 検索: first(), last(), contains()
    +-- ソート: sort(), sortBy(), reverse()
    +-- グループ化: groupBy(), keyBy(), chunk()
    |
    v
[結果（Collection or 値）]
```

### 2.2 クラス構成

| クラス名 | 役割 |
|---------|------|
| Collection | メインコレクションクラス |
| LazyCollection | 遅延評価コレクション |
| Enumerable | コレクションインターフェース |
| EnumeratesValues | 共通操作トレイト |

### 2.3 主要メソッド

#### 作成

| メソッド | 説明 | 引数 | 戻り値 |
|---------|------|------|--------|
| `make()` | 新規コレクション作成 | `$items` | `static` |
| `wrap()` | 値をコレクションでラップ | `$value` | `static` |
| `unwrap()` | コレクションを配列に展開 | `$value` | `array` |
| `range()` | 範囲指定でコレクション作成 | `$from, $to, $step` | `static` |
| `times()` | 指定回数コールバック実行 | `$number, $callback` | `static` |
| `lazy()` | LazyCollectionに変換 | - | `LazyCollection` |

#### 変換

| メソッド | 説明 | 引数 | 戻り値 |
|---------|------|------|--------|
| `map()` | 各要素を変換 | `$callback` | `static` |
| `mapWithKeys()` | キー付きで変換 | `$callback` | `static` |
| `pluck()` | 指定キーの値を抽出 | `$value, $key` | `static` |
| `flatMap()` | 変換後にフラット化 | `$callback` | `static` |
| `transform()` | 自身を変換（破壊的） | `$callback` | `$this` |
| `collapse()` | ネスト配列をフラット化 | - | `static` |
| `flatten()` | 多次元配列をフラット化 | `$depth` | `static` |

#### 絞り込み

| メソッド | 説明 | 引数 | 戻り値 |
|---------|------|------|--------|
| `filter()` | 条件に合う要素を抽出 | `$callback` | `static` |
| `reject()` | 条件に合わない要素を抽出 | `$callback` | `static` |
| `where()` | キー・値で絞り込み | `$key, $operator, $value` | `static` |
| `whereIn()` | 値がリストに含まれるもの | `$key, $values` | `static` |
| `whereNotIn()` | 値がリストに含まれないもの | `$key, $values` | `static` |
| `whereNull()` | 値がnullのもの | `$key` | `static` |
| `whereNotNull()` | 値がnullでないもの | `$key` | `static` |
| `unique()` | 重複を除去 | `$key` | `static` |
| `take()` | 先頭/末尾から取得 | `$limit` | `static` |
| `skip()` | 先頭から除外 | `$count` | `static` |

#### 集計

| メソッド | 説明 | 引数 | 戻り値 |
|---------|------|------|--------|
| `count()` | 要素数 | - | `int` |
| `sum()` | 合計 | `$callback` | `mixed` |
| `avg()` / `average()` | 平均 | `$callback` | `mixed` |
| `min()` | 最小値 | `$callback` | `mixed` |
| `max()` | 最大値 | `$callback` | `mixed` |
| `median()` | 中央値 | `$key` | `float\|int\|null` |
| `mode()` | 最頻値 | `$key` | `array\|null` |
| `reduce()` | 畳み込み | `$callback, $initial` | `mixed` |

#### 検索

| メソッド | 説明 | 引数 | 戻り値 |
|---------|------|------|--------|
| `first()` | 最初の要素 | `$callback, $default` | `mixed` |
| `last()` | 最後の要素 | `$callback, $default` | `mixed` |
| `firstWhere()` | 条件に合う最初の要素 | `$key, $operator, $value` | `mixed` |
| `contains()` | 要素存在チェック | `$key, $operator, $value` | `bool` |
| `search()` | 要素のインデックス検索 | `$value, $strict` | `mixed` |
| `get()` | キーで取得 | `$key, $default` | `mixed` |

#### ソート

| メソッド | 説明 | 引数 | 戻り値 |
|---------|------|------|--------|
| `sort()` | ソート | `$callback` | `static` |
| `sortBy()` | キーでソート | `$callback, $options, $descending` | `static` |
| `sortByDesc()` | キーで降順ソート | `$callback, $options` | `static` |
| `sortKeys()` | キーでソート | `$options, $descending` | `static` |
| `reverse()` | 順序反転 | - | `static` |
| `shuffle()` | シャッフル | `$seed` | `static` |

#### グループ化・分割

| メソッド | 説明 | 引数 | 戻り値 |
|---------|------|------|--------|
| `groupBy()` | グループ化 | `$groupBy, $preserveKeys` | `static` |
| `keyBy()` | キーを変更 | `$keyBy` | `static` |
| `chunk()` | 分割 | `$size` | `static` |
| `partition()` | 条件で2分割 | `$callback` | `static` |
| `split()` | 指定数に分割 | `$numberOfGroups` | `static` |

### 2.4 ビジネスルール

1. **イミュータブル操作**
   - ほとんどのメソッドは新しい Collection を返す
   - 元のコレクションは変更されない
   - `transform()`, `put()`, `forget()` 等は破壊的

2. **チェーンメソッド**
   - 各メソッドは `static` を返すためチェーン可能
   - 最終的に `all()`, `toArray()` で配列に変換

3. **コールバック引数**
   - 多くのメソッドはコールバック関数を受け取る
   - コールバックは `($value, $key)` の順で引数を受け取る

4. **遅延評価**
   - `lazy()` で LazyCollection に変換可能
   - 大量データの処理でメモリ効率が向上

## 3. 入出力仕様

### 3.1 入力

| 項目 | 型 | 説明 |
|-----|-----|------|
| items | `array\|Arrayable\|iterable` | コレクション化するデータ |

### 3.2 出力

| 項目 | 型 | 説明 |
|-----|-----|------|
| collection | `Collection` | コレクションインスタンス |
| array | `array` | `all()`, `toArray()` で配列変換 |

## 4. 依存関係

### 4.1 内部依存

| パッケージ | 用途 |
|-----------|------|
| Illuminate\Support\Arr | 配列操作ヘルパー |
| Illuminate\Support\Traits\EnumeratesValues | 列挙操作トレイト |
| Illuminate\Support\Traits\Macroable | マクロ拡張 |

### 4.2 外部依存

| パッケージ | 用途 |
|-----------|------|
| なし | 外部依存なし |

## 5. エラー処理

| エラー種別 | 発生条件 | 処理内容 |
|-----------|---------|---------|
| InvalidArgumentException | 不正な引数 | 例外スロー |
| ItemNotFoundException | `firstOrFail()` で要素なし | 例外スロー |
| MultipleItemsFoundException | `sole()` で複数要素 | 例外スロー |

## 6. コードリーディングガイド

### 6.1 推奨読解順序

1. **クラス定義とインターフェース** (`Collections/Collection.php`)
   - **23-28行目**: クラス定義、Enumerable実装、トレイト使用
   - **35行目**: `$items` プロパティ - 内部データ格納

2. **コンストラクタと基本操作**
   - **42-45行目**: コンストラクタ - Arrayable対応
   - **55-58行目**: `range()` - 範囲指定作成
   - **65-68行目**: `all()` - 配列取得
   - **75-78行目**: `lazy()` - LazyCollection変換

3. **統計メソッド**
   - **86-107行目**: `median()` - 中央値計算
   - **115-133行目**: `mode()` - 最頻値計算

4. **変換メソッド**
   - **140-143行目**: `collapse()` - 配列フラット化
   - **150-173行目**: `collapseWithKeys()` - キー保持フラット化

5. **検索メソッド**
   - **183-194行目**: `contains()` - 要素存在チェック
   - **203-214行目**: `containsStrict()` - 厳密比較

6. **比較メソッド**
   - **264-267行目**: `diff()` - 差集合
   - **287-290行目**: `diffAssoc()` - キー・値の差集合
   - **310-313行目**: `diffKeys()` - キーの差集合

7. **重複検出**
   - **336-355行目**: `duplicates()` - 重複要素取得

### 6.2 プログラム呼び出し階層図

```
collect($array)
└── Collection::make($array)
    └── new Collection($array)
        └── EnumeratesValues::getArrayableItems()

$collection->map($callback)
└── EnumeratesValues::map($callback)
    └── array_map($callback, $this->items)
        └── new static($result)

$collection->filter($callback)
└── EnumeratesValues::filter($callback)
    └── array_filter($this->items, $callback)
        └── new static($result)

$collection->where($key, $value)
└── EnumeratesValues::where($key, $operator, $value)
    └── $this->filter($this->operatorForWhere(...))
```

### 6.3 データフロー図

```
[入力データ（配列/Arrayable）]
    |
    v
[Collection::__construct()]
    |
    +-- getArrayableItems() で配列化
    |
    v
[$this->items に格納]
    |
    +-- map() --> 新しい Collection
    +-- filter() --> 新しい Collection
    +-- reduce() --> 単一値
    +-- first() --> 単一要素
    |
    v
[all() / toArray() で配列出力]
```

### 6.4 読解のコツ

- **トレイト分離**: 共通操作は `EnumeratesValues` トレイトに集約
- **静的ファクトリ**: `static` を返すことで継承クラスも正しく動作
- **Arrayable対応**: コンストラクタで `Arrayable` インターフェースを自動変換
- **オペレーター構文**: `where($key, '>', $value)` のような SQL 風構文サポート

### 6.5 関連ファイル一覧

| ファイルパス | 種別 | 役割 |
|------------|------|------|
| `src/Illuminate/Collections/Collection.php` | Collection | メインクラス（Support名前空間にエイリアス） |
| `src/Illuminate/Support/Collection.php` | Collection | Support名前空間のエイリアス |
| `src/Illuminate/Collections/LazyCollection.php` | Collection | 遅延評価コレクション |
| `src/Illuminate/Support/Enumerable.php` | Interface | コレクションインターフェース |
| `src/Illuminate/Support/Traits/EnumeratesValues.php` | Trait | 列挙操作の共通実装 |
| `src/Illuminate/Collections/Arr.php` | Helper | 配列操作ヘルパー |

## 7. 使用例

```php
use Illuminate\Support\Collection;

// コレクション作成
$collection = collect([1, 2, 3, 4, 5]);

// 変換
$doubled = $collection->map(fn ($item) => $item * 2);
// [2, 4, 6, 8, 10]

// 絞り込み
$evens = $collection->filter(fn ($item) => $item % 2 === 0);
// [2, 4]

// 集計
$sum = $collection->sum(); // 15
$avg = $collection->avg(); // 3

// オブジェクト配列の操作
$users = collect([
    ['name' => 'John', 'age' => 30],
    ['name' => 'Jane', 'age' => 25],
    ['name' => 'Bob', 'age' => 35],
]);

// pluck: 特定キーの値を抽出
$names = $users->pluck('name');
// ['John', 'Jane', 'Bob']

// where: 条件絞り込み
$adults = $users->where('age', '>=', 30);

// sortBy: ソート
$sorted = $users->sortBy('age');

// groupBy: グループ化
$byAge = $users->groupBy(fn ($user) => $user['age'] >= 30 ? 'senior' : 'junior');

// チェーンメソッド
$result = collect($data)
    ->filter(fn ($item) => $item['active'])
    ->map(fn ($item) => $item['name'])
    ->unique()
    ->sort()
    ->values()
    ->all();

// 遅延評価（大量データ向け）
$lazy = LazyCollection::make(function () {
    $handle = fopen('large-file.csv', 'r');
    while ($line = fgets($handle)) {
        yield str_getcsv($line);
    }
})->filter(fn ($row) => $row[0] === 'active')
  ->take(100);
```

## 8. 改版履歴

| バージョン | 日付 | 変更内容 |
|-----------|------|---------|
| 1.0.0 | - | 初版作成 |
