気が付いたら前の記事から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)みたいな感じで
なんだかんだ、使ってると手になじんでくるものです。