array_reduceで配列を1つの値に畳み込む

array_reduceは、配列の各要素をコールバックに順番に渡しながら、最終的に1つの値へ畳み込む関数です。合計や集計、グルーピングのような「配列をなにかに要約する」処理でよく使います。

foreachで書けば済む処理をわざわざarray_reduceにする必要はないんですが、集計ロジックを1つの式として閉じ込めたいときには便利です。ただ、初期値の扱いとキーが落ちる点でハマったことがある人も多いんじゃないでしょうか。今日はそのあたりを整理します。

array_reduceの基本の書き方

シグネチャはこうなっています。

array_reduce(array $array, callable $callback, mixed $initial = null): mixed

コールバックは function($carry, $item) の形で、第1引数がここまでの積算結果(キャリー)、第2引数が今回処理する要素です。戻り値が次のキャリーになります。合計を出す例です。

$prices = [1200, 800, 3500];

$total = array_reduce(
    $prices,
    fn($carry, $item) => $carry + $item,
    0
);

echo $total; // 5500

第3引数の初期値を渡すのは、単に「最初のキャリーを何にするか」を決めているだけです。数値の合計なら0、配列を作るなら空配列を渡します。

初期値を省略するとどうなるか

初期値はデフォルトでnullです。ここが最初のハマりどころで、配列が空だった場合にarray_reduceはエラーにならず、黙ってnullを返します。

$empty = [];

$result = array_reduce($empty, fn($carry, $item) => $carry + $item);

var_dump($result); // NULL

合計を求めるつもりでこれをそのまま数値として使うと、nullとの演算やnullを前提にしない後続処理で型エラーが出ます。空配列が来る可能性がある処理では、初期値を明示するか、使う前にnullチェックを入れておいた方が安全です。

グルーピングにも使える

初期値に配列を渡せば、集計だけでなくグルーピングにも使えます。ユーザーをステータス別にまとめる例です。

$users = [
    ['name' => '田中', 'status' => 'active'],
    ['name' => '佐藤', 'status' => 'inactive'],
    ['name' => '鈴木', 'status' => 'active'],
];

$grouped = array_reduce(
    $users,
    function (array $carry, array $user) {
        $carry[$user['status']][] = $user['name'];
        return $carry;
    },
    []
);

// $grouped = ['active' => ['田中', '鈴木'], 'inactive' => ['佐藤']]

こういう「配列を配列に畳み込む」処理は、foreachで書くよりも1つの式にまとまって、集計ロジックの入出力がはっきりします。ただしコールバックの中身が長くなってくると、逆に読みにくくなるので、3〜4行を超えるならforeachに戻した方が素直だと個人的には思います。

キーは渡ってこない

array_reduceのコールバックには値しか渡らず、元の配列のキーは渡されません。連想配列を渡してもキー情報は使えないので、キーごとに処理を変えたい場合は事前にarray_keys()と組み合わせるか、array_walkなど別の関数を検討することになります。

まとめ

array_reduceは、配列を1つの値や別の配列に要約するときの選択肢の1つです。初期値を省略すると空配列でnullが返ってくる点と、コールバックにキーが渡らない点さえ押さえておけば、合計やグルーピングの処理をすっきり書けます。逆に処理が込み入ってきたら、無理に畳み込まずforeachに戻す判断も大事だと思います。

よくある質問

Q. array_reduceとarray_mapの違いは何ですか。
A. array_mapは配列の各要素を変換して同じ要素数の配列を返すのに対し、array_reduceは配列全体を1つの値(または任意の構造)に畳み込みます。目的が「変換」か「集約」かで使い分けます。

Q. array_reduceは配列の途中で処理を打ち切れますか。
A. 標準の仕組みでは途中終了できません。全要素を必ず走査するので、条件次第で早期終了したい場合はforeachとbreakを使う方が適しています。

Q. 初期値を渡さないとどうなりますか。
A. デフォルトはnullで、配列が空の場合はそのままnullが返ります。空配列が来る可能性がある処理では初期値を明示しておくと安全です。

類似投稿

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です