Posted on

Hashはいいぞ Hash::map編

気が付いたら前の記事から1年半以上空いてしまいました。それだけみんな忙しかったといえばそうなのですが、ようやっと時間ができたので、何を書こうかなと思ったとき、そういえば近くの人にHash::map教えてないなって思い出したんです。

これ、最初のうちはかなり読みにくい印象あると思うんです。ラムダ関数慣れが要るという感じで…

ここまでくるとforeachと大差ないっちゃ大差ないところもあります。
Hash::reduceともなるとさらに差がなくて、正直どっちで書けばいいか自分でも迷います。

それでも、配列を「ループで一つ一つ確認する」というforeachの見え方と、
配列を「各要素にまとめて適用する」というmapの見え方ってやっぱり違うと思うんです。

  1. // Model->find('all') したときありがちな配列  
  2. $data = [  
  3.     o => [  
  4.         'Color' => [  
  5.             'id'=>'1',  
  6.             'name'=>ゴールド',  
  7.             'red'=>'255',  
  8.             'green'=>'215',  
  9.             'blue'=>'0',  
  10.         ]  
  11.     ],  
  12.     1 => [  
  13.         'Color'=>[  
  14.             'id'=>'2',  
  15.             'name'=>'シルバー',  
  16.             'red'=>'192',  
  17.             'green'=>'192',  
  18.             'blue'=>'192',  
  19.         ]  
  20.     ],  
  21.     2 => [  
  22.         'Color'=>[  
  23.             'id'=>'3',  
  24.             'name'=>'ブロンズ',  
  25.             'red'=>'154',  
  26.             'green'=>'98',  
  27.             'blue'=>'41',  
  28.         ]  
  29.     ]  
  30. ];  
  31.   
  32. //色名と16進コードの配列を作る  
  33. $result = Hash::map($data,'{n}.Color',function($item){  
  34.     return [   
  35.         'name' => $item['name'],  
  36.         'hex_code' => sprintf("#%02x%02x%02x",$item['red'],$item['green'],$item['blue'])  
  37.     ];  
  38. });  
  39.   
  40. /** 
  41.  
  42. $result = [ 
  43.     0 => [ 
  44.         'name' => 'ゴールド', 
  45.         'hex_code' => '#ffd700', 
  46.     ], 
  47.     1 => [ 
  48.        'name' => 'シルバー', 
  49.        'hex_code' => '#c0c0c0', 
  50.     ], 
  51.     2 => [ 
  52.        'name' => 'ブロンズ', 
  53.        'hex_code' => '#9a6229', 
  54.     ], 
  55. ]; 
  56.  
  57. */  
  58.   
  59. //やってることは以下のforeachとあんまり差はない  
  60. $result_foreach = [];  
  61. foreach($data as $color){  
  62.     $result_foreach[] = [  
  63.         'name' => $color['Color']['name'],  
  64.         'hex_code' =>  sprintf("#%02x%02x%02x",$item['Color']['red'],$item['Color']['green'],$item['Color']['blue'])  
  65.     ];  
  66. }  

foreachとあんまり変わらないなら、なぜこういう書き方をするかと考察したとき、いくつか強みっぽいところはあります

深い階層からもパスで引っ張ってきてくれる
深い深い配列の奥にあっても、Hashのパス記法を使えば、何重foreachを使わずとも。
引っ張ってくる個数と結果の配列は要素個数が同じで、キーは0始まり連番
foreachだとソースを読まないとそういう結果の予想は付かない
ラムダ関数の中は独自スコープ
外側と変数名がかぶることを気にしなくていい。外側の変数を使いたいときはfunction($item)use($outside_var)みたいな感じで

なんだかんだ、使ってると手になじんでくるものです。