Ginq は LINQ の PHP 実装の一つ。とてもよい。
Ginq に限らず LINQ 系全般に通じる話です。
PHP で配列内のオブジェクトを条件によってグループ分けする、ということをたまにやりたい場面があります。Ginq では次のように書くことができます。
// 例えばこんなクラスのオブジェクト配列があるとする
class EventSlate {
/** @type string */
public $date;
/** @type string */
public $title;
public function __construct($date, $title)
{
$this->date = $date;
$this->title = $title;
}
}
$events = [
new EventSlate('2014/10/15', '寿司駆動ハンズオン'),
new EventSlate('2014/10/15', 'PHPもくもく会'),
new EventSlate('2014/10/31', 'ハロウィンIT勉強会'),
new EventSlate('2014/10/31', 'git push -f'),
new EventSlate('2014/10/31', '仮装サーバ構築勉強会')
];
// ↑ を日付ごとにまとめてキーに日付を設定するには ↓ のようにする
$events_by_date = Ginq::from($events)
->groupBy(function(EventSlate $es) {
return $es->date;
})
->map(function(GroupingGinq $g) {
return $g->toList();
})
->toArray();
print_r($events_by_date);
出力は以下のようになります。
Array
(
[2014/10/15] => Array
(
[0] => EventSlate Object
(
[date] => 2014/10/15
[title] => 寿司駆動ハンズオン
)
[1] => EventSlate Object
(
[date] => 2014/10/15
[title] => PHPもくもく会
)
)
[2014/10/31] => Array
(
[0] => EventSlate Object
(
[date] => 2014/10/31
[title] => ハロウィンIT勉強会
)
[1] => EventSlate Object
(
[date] => 2014/10/31
[title] => git push -f
)
[2] => EventSlate Object
(
[date] => 2014/10/31
[title] => 仮装サーバ構築勉強会
)
)
)
「オブジェクトをグループ化」というと groupBy
が思い浮かびますが、検索しても「グループ化して集計」とか「グループ化して平均値を計算」とかばかりで、オブジェクトをそのままグループ分けして連想配列にする方法は見つかりませんでした。
要するに、groupBy
という機能自体は flatMap
の逆で、複数の集合のシーケンスを作成するものなんですね。さらに groupBy
は自動的にキーを設定してくれるみたいで、とても使い勝手がよいですね。