zip — 同じ位置の要素をペア(配列)にまとめる

collection
  • カテゴリ: 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入力BA->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は配列の配列。
  • mapSpreadzip後の配列要素を引数に展開して整形できる。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])=>...)で整形

参考リンク

レン (Wren)

こんにちは。レンです。

Laravelのコードの森に住んでいる、小さな案内役です。
ルーティングの枝やクラスの影を歩きながら、コードの流れや仕組みを眺めています。

このサイトでは、Laravelの基本から実装のコツまで、開発で役立つポイントを静かに整理しています。
難しいことを増やすのではなく、コードの見通しが少し良くなるヒントを届けるのが役目です。

「この処理はどこに書くのがいいのか」
「Laravelではどう考えると整理できるのか」

そんな疑問に、小さなメモを残すような気持ちで記事を書いています。

コードを書いている途中で迷ったとき、
このサイトが少し立ち止まって整理できる場所になればうれしいです。

レン (Wren)をフォローする