気が付いたら前の記事から1年半以上空いてしまいました。それだけみんな忙しかったといえばそうなのですが、ようやっと時間ができたので、何を書こうかなと思ったとき、そういえば近くの人にHash::map教えてないなって思い出したんです。
これ、最初のうちはかなり読みにくい印象あると思うんです。ラムダ関数慣れが要るという感じで…
ここまでくるとforeachと大差ないっちゃ大差ないところもあります。
Hash::reduceともなるとさらに差がなくて、正直どっちで書けばいいか自分でも迷います。
それでも、配列を「ループで一つ一つ確認する」というforeachの見え方と、
配列を「各要素にまとめて適用する」というmapの見え方ってやっぱり違うと思うんです。
// Model->find('all') したときありがちな配列 $data = [ o => [ 'Color' => [ 'id'=>'1', 'name'=>ゴールド', 'red'=>'255', 'green'=>'215', 'blue'=>'0', ] ], 1 => [ 'Color'=>[ 'id'=>'2', 'name'=>'シルバー', 'red'=>'192', 'green'=>'192', 'blue'=>'192', ] ], 2 => [ 'Color'=>[ 'id'=>'3', 'name'=>'ブロンズ', 'red'=>'154', 'green'=>'98', 'blue'=>'41', ] ] ]; //色名と16進コードの配列を作る $result = Hash::map($data,'{n}.Color',function($item){ return [ 'name' => $item['name'], 'hex_code' => sprintf("#%02x%02x%02x",$item['red'],$item['green'],$item['blue']) ]; }); /** $result = [ 0 => [ 'name' => 'ゴールド', 'hex_code' => '#ffd700', ], 1 => [ 'name' => 'シルバー', 'hex_code' => '#c0c0c0', ], 2 => [ 'name' => 'ブロンズ', 'hex_code' => '#9a6229', ], ]; */ //やってることは以下のforeachとあんまり差はない $result_foreach = []; foreach($data as $color){ $result_foreach[] = [ 'name' => $color['Color']['name'], 'hex_code' => sprintf("#%02x%02x%02x",$item['Color']['red'],$item['Color']['green'],$item['Color']['blue']) ]; }
foreachとあんまり変わらないなら、なぜこういう書き方をするかと考察したとき、いくつか強みっぽいところはあります
- 深い階層からもパスで引っ張ってきてくれる
- 深い深い配列の奥にあっても、Hashのパス記法を使えば、何重foreachを使わずとも。
- 引っ張ってくる個数と結果の配列は要素個数が同じで、キーは0始まり連番
- foreachだとソースを読まないとそういう結果の予想は付かない
- ラムダ関数の中は独自スコープ
- 外側と変数名がかぶることを気にしなくていい。外側の変数を使いたいときはfunction($item)use($outside_var)みたいな感じで
なんだかんだ、使ってると手になじんでくるものです。