Posted on

Hashはいいぞ Hash::map編

気が付いたら前の記事から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)みたいな感じで

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