40秒で把握するCollectionのchunkWhile()

Laravel11公式ドキュメントのCollectionメソッド chunkWhileについてみていきます。段階的に見ていきますが、LaravelのCollectionについて把握していない方は、以下の記事を先に見るとこの記事が読みやすくなると思います。

LaravelのCollectionに触れる

この記事で得られること

  • chunkWhile()の概要
  • chunkWhile()の実装コードを見る体験

メソッドの概要を見る

Laravel – The PHP Framework For Web Artisans

公式ドキュメントを日本語訳してからの引用

この**chunkWhileメソッドは、指定されたコールバックの評価に基づいて、コレクションを複数の小さなコレクションに分割します。$chunk**クロージャに渡される変数は、前の要素を検査するために使用できます。

$collection = collect(str_split('AABBCCCD'));
 
$chunks = $collection->chunkWhile(function (string $value, int $key, Collection $chunk) {
    return $value === $chunk->last();
});
 
$chunks->all();
 
// [['A', 'A'], ['B', 'B'], ['C', 'C', 'C'], ['D']]
  • 指定されたコールバックの評価に基づいてコレクションを複数の小さなコレクションに分割する
  • $chunk クロージャに渡される変数は前の要素を検査するために使用できる

メソッドのソースを見る

概要は何となく掴めてきたので早速ソースを見ていきます。

vendor/laravel/framework/src/Illuminate/Collections/Collection.php

    /**
     * Chunk the collection into chunks with a callback.
     *
     * @param  callable(TValue, TKey, static<int, TValue>): bool  $callback
     * @return static<int, static<int, TValue>>
     */
    public function chunkWhile(callable $callback)
    {
        return new static(
            $this->lazy()->chunkWhile($callback)->mapInto(static::class)
        );
    }

CursorAI(GPT4)に聞いて分かったことも交えつつ解説します。

情報が詰め込まれていますが、段階的に見ていきます。

return new static(
    $this->lazy()->chunkWhile($callback)->mapInto(static::class)
);
$this→lazy() 

元のコレクションを遅延評価しているようです。遅延評価とはデータが必要になるまで処理を行わないという処理方式です。

通常、プログラムのデータはメモリに全て読み込まれてからデータの評価を行います。しかし、遅延評価の場合はデータが条件にあった時点でデータの評価を行います。これにより、データが大量にあった場合でも必要なデータにだけ処理を行うため、メモリの使用効率が良くなり、パフォーマンスが向上します。

chunkWhile($callback)

元のコレクションで指定されたコールバックに基づいて複数の小さなグループに分けます。

$callback が各データを評価し、新しいグループの作成を開始するかを決定しています。

また、再起的に呼び出されているように見えますが、chunkWhile()は一度だけしか呼び出されません。

mapInto(static::class)

複数に分かれた各グループを新しくCollectionのインスタンスにします。これにより、分かれた小さなグループもコレクションとして操作をすることが可能になります。

使ってみる

以下は、元のコレクションのデータを奇数と偶数に分けるプログラムです。

$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9]);

$chunks = $collection->chunkWhile(fn (int $value, int $key, Collection $chunk) => $value % 2 === 0);

dd($chunks->all());

結果は5つのグループに分かれました。chunkWhileは条件が変わるごとに新しいグループを作成するため、このようなグループに分かれるのですね。

もし、奇数と偶数のみの二つのグループに分けたい場合はpartition()が使えます。

list($evens, $odds) = $collection->partition(fn (int $value) => $value % 2 === 0);

まとめ

コレクションのchunkWhileメソッドは以下のような特徴を持つ

  • 指定されたコールバックに基づいて複数の小さなコレクションに分ける
  • その実装はlazy()による遅延評価と指定されたコールバックによる新しいグループを作る基準の制御によってなされている。

正直、今回は知らないことだらけで言語や技術を問わず「アプリケーションを作れるほどのフレームワーク」でどのような概念が存在しているのかを知ることの大切さを改めて知りました。ここで知ったことはLaravel以外にも役に立つと思うので浅いですが、早めに知ることができて良かったです。

おまけ CursorAI(GPT-4)に聞いたときに使った質問文

1ラウンド目

下記はLaravelのCollectionクラス内の記述です。
コードの解説を以下の点を踏まえてお願いします。
- 段階的に行う
- 小学生でも分かるような言葉を使う
- コードの引用を混じえる

"""
    /**
     * Chunk the collection into chunks with a callback.
     *
     * @param  callable(TValue, TKey, static<int, TValue>): bool  $callback
     * @return static<int, static<int, TValue>>
     */
    public function chunkWhile(callable $callback)
    {
        return new static(
            $this->lazy()->chunkWhile($callback)->mapInto(static::class)
        );
    }
"""

2ラウンド目

ここにおける遅延評価とは何ですか?

3ラウンド目

chunkWhileを再起的に呼び出していると思いますが、どのような処理になりますか?

「知りたいことは分かるけれど、うーん…」みたいなインプットしか出せていないので、もっと質問力というか引き出す力が欲しい(切実)

コメント

タイトルとURLをコピーしました