avgメソッド Collectionメソッドソースコードリーディング100本ノック2本目
メソッド概要
avgメソッドは、指定したキーの平均値を返します。
<?php $average = collect([['foo' => 10], ['foo' => 10], ['foo' => 20], ['foo' => 40]])->avg('foo'); // 20 $average = collect([1, 1, 2, 4])->avg(); // 2
average
メソッドも同じ処理です。
ソースコードリーディング
avg メソッド
では早速、ソースコードリーディングをやって行きましょう。
<?php /** * Get the average value of a given key. * * @param callable|string|null $callback * @return mixed */ public function avg($callback = null) { $callback = $this->valueRetriever($callback); $items = $this->map(function ($value) use ($callback) { return $callback($value); })->filter(function ($value) { return ! is_null($value); }); if ($count = $items->count()) { return $items->sum() / $count; } }
後で解説しますが valueRetriever
メソッドは、$callback
をコールバックとして読み取れる値に整形するメソッドです。
$callback
の戻り値を、 map
メソッドを使って Collection
へ整形します。
戻り値が null
だった時は、 Collection
に含めません。 null
を平均の対象へと含めないようにする意図のようですね。
最後に Collection
内の値の平均値を返す…といった処理になります。
参考:
valueRetriever メソッド
<?php /** * Get a value retrieving callback. * * @param string $value * @return callable */ protected function valueRetriever($value) { if ($this->useAsCallable($value)) { return $value; } return function ($item) use ($value) { return data_get($item, $value); }; }
$callback
を、コールバックとして読み取れる値に整形するメソッドです。
最初にそもそもコールバックとして読み取れる値だったら、そのまま値を返します。
コールバックとして読み取れない値だったら、コールバックとして読み取れる無名関数を返します。例えば以下のようなコードがあったとします。
$callback = $this->valueRetriever($value) $callback($item)
この場合、 $callback($item)
は以下のようになります。
$callback($item) = function ($item) use ($value) { return data_get($item, $value); }
data_get
は、配列やドット区切りのオブジェクトから要素(配列 or データ型の値)を取り出すヘルパメソッドになります(data_get
ヘルパメソッドについては、別の記事にて解説します)。
$item
が配列だったり Collection
だった時のために、このような処理になっているようです。
参考:
useAsCallable メソッド
関数として呼び出し可能 かつ 文字列ではないかを返します。
呼び出し可能な関数名ではなく、関数そのものか判別したい時に使うようです。
<?php /** * Determine if the given value is callable, but not a string. * * @param mixed $value * @return bool */ protected function useAsCallable($value) { return ! is_string($value) && is_callable($value); }
最後に
この記事を書いているうちに、 Laravel 5.7 -> 5.8 へとバージョンアップしました。
もたもたしているとすぐバージョンが上がってしまい、過去に書いた Collection
メソッドをまた再度検証する…なんてことになってしまうので他のメソッドもどんどん書いていこうと思います!
次は chunk
メソッドです!