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