- カテゴリ: collection
- 掲載バージョン: Laravel 12・PHP 8.4
- 名前空間 / FQCN / コマンド:
Illuminate\Support\Collection::zip - 関連: combine / mapSpread / transpose / crossJoin / map
- 変更履歴: 特筆事項なし(現行バージョンで利用可)
要点(TL;DR)
- コレクションと同じインデックスの要素同士をまとめ、
[[a1,b1],[a2,b2],...]の形にする - 例:
collect(['A','B'])->zip([1,2]) // [['A',1],['B',2]] - 罠:
- 短い方に合わせて打ち切り(余りは捨てられる)
- キーは再採番(0,1,2…)し、元のキーは保持されない
- 複数列をオブジェクト化したい場合は
mapSpread()等で整形が必要
概要
zipは、基底コレクションと渡した配列/コレクションの同じ位置の要素をペア(配列)に束ねるメソッドです。複数データ源を「横持ち」で扱いたいときに有効で、後続のmapSpreadなどでDTOや連想配列へ整形して使います。要素数が異なる場合は短い方の長さで結果が切られる点に注意します。
構文 / シグネチャ
public function zip($items): Illuminate\Support\Collection
- 引数(表) 引数 型 必須 既定値 説明 $items array Collection Traversable ✅
- 戻り値:
Collection(各要素は配列。[valueFromBase, valueFromItems]形式) - 例外/副作用:例外なし。非破壊(元コレクションは変更されない)
コレクション固有の事項
- チェーン可:可(新しい
Collectionを返す) - 破壊的/非破壊:非破壊
- キー保持:保持しない(0始まりで再採番)
- LazyCollection:対応(遅延評価で処理可能)
- 計算量の目安:O(n)(
nは束ねられる最短長)
入出力対応表(サンプル)
| 入力A | 入力B | A->zip(B) の出力 |
|---|---|---|
['a','b'] | [1,2] | [['a',1],['b',2]] |
['a','b','c'] | [1] | [['a',1]](短い方に合わせる) |
['a'=>10,'b'=>20] | ['x'=>1,'y'=>2] | [[10,1],[20,2]](キーは無視・値だけ束ねる) |
使用例
最小例
use Illuminate\Support\Collection;
$names = collect(['Alice', 'Bob']);
$scores = [90, 80];
$pairs = $names->zip($scores);
// collect([ ['Alice', 90], ['Bob', 80] ])
$pairs->all(); // [['Alice', 90], ['Bob', 80]]
実務例(DTO化:zip + mapSpread)
use Illuminate\Support\Collection;
$userIds = collect([101, 102, 103]);
$userNames = collect(['Alice', 'Bob', 'Charlie']);
// zip は [[101,'Alice'], [102,'Bob'], ...] の形になる
$users = $userIds->zip($userNames)
->mapSpread(fn (int $id, string $name) => (object) ['id' => $id, 'name' => $name]);
/*
[
(object) ['id' => 101, 'name' => 'Alice'],
(object) ['id' => 102, 'name' => 'Bob'],
(object) ['id' => 103, 'name' => 'Charlie'],
]
*/
実務例(余りを捨てる性質に注意)
$left = collect([1, 2, 3, 4]);
$right = collect(['A', 'B']); // 短い
$z = $left->zip($right)->all(); // [[1,'A'], [2,'B']] → 3,4 は捨てられる
よくある落とし穴・注意
- 長さ不一致:短い方に切り詰められる。足りない分を補完したいなら
pad()で事前調整や、zip後にmapでデフォルト値を当てる。 - キー喪失:元キーは使われない。キーを活かしたいなら
combine()等を検討。 - 多列の整形:
zip結果は配列の配列。列ごとにプロパティへ格納するにはmapSpread()やmap(fn([$a,$b]) => ...)で整形する。 - 順序依存:インデックスで束ねるため、並び順が揃っていることが前提。別ソースからのデータはソートやインデックス整合を取ってから
zipする。
代替・関連APIとの比較
combine:[keys]->combine([values])でキー=>値の連想配列化。インデックス一致前提だがキーが活きる。zipは配列の配列。mapSpread:zip後の配列要素を引数に展開して整形できる。zipとセットで使う場面が多い。transpose:二次元配列の行列入れ替え。複数列を「縦横」反転したい場合に有効。crossJoin:直積(全組み合わせ)。zipは同じ位置だけを束ねる点が対照的。
テスト例(Pest)
<?php
use Illuminate\Support\Collection;
it('zips elements by index', function () {
$a = collect(['X', 'Y']);
$b = collect([1, 2]);
$z = $a->zip($b);
expect($z->all())->toBe([['X', 1], ['Y', 2]]);
// キーは再採番されること
expect($z->keys()->all())->toBe([0, 1]);
});
トラブルシュート(エラー別)
| 症状/エラー | 原因 | 対処 |
|---|---|---|
| 結果が途中で切れている | 片方が短い | 事前にcount()で長さ確認・pad()で補完・結合元データの整合を取る |
| 元のキーが失われた | zipはキー再採番仕様 | キーが必要ならcombine()や、map()でキーを再構築 |
| DTOにしづらい | 配列の配列のまま扱っている | mapSpread()またはmap(fn([$a,$b])=>...)で整形 |
参考リンク
- Laravel公式「Collections: zip」
https://laravel.com/docs/12.x/collections#method-zip - Laravel公式「Collections: combine」
https://laravel.com/docs/12.x/collections#method-combine - Laravel公式「Collections: mapSpread」
https://laravel.com/docs/12.x/collections#method-mapspread - Laravel公式「Collections: transpose」
https://laravel.com/docs/12.x/collections#method-transpose - Laravel公式「Collections: crossJoin」
https://laravel.com/docs/12.x/collections#method-crossjoin

