多次元配列の要素を特定の値をキーとしてマージする

2 分で読める

FuelPHPのArrクラスでは、非常に便利な配列操作のヘルパー関数が用意されているのですが、ありそうでなかったので…

それから、記事タイトルが何言ってるのか正直自分もよく分からないので例を。

array(
    array(
        'group' => 'CV1',
        'name' => 'Miku'
    ),
    array(
        'group' => 'CV2',
        'name' => 'Rin'
    ),
    array(
        'group' => 'CV2',
        'name' => 'Len'
    )
);

のような入力を与えた時に、

array(
    'CV1' => array(
        array(
            'group' => 'CV1',
            'name' => 'Miku'
        )
    ),
    'CV2' => array(
        array(
            'group' => 'CV2',
            'name' => 'Rin'
        ),
        array(
            'group' => 'CV2',
            'name' => 'Len'
        )
    )
);

あるいは、

array(
    'CV1' => array(
        'Miku'
    ),
    'CV2' => array(
        'Rin',
        'Len'
    )
);

のような出力を得たい、ということです。あるキーの同じ値同士でまとめるような感覚でしょうか。

とりあえず以下のように書いてみました。

class Arr extends \Fuel\Core\Arr
{
	/**
	 * @param array  $assoc     変換する配列
	 * @param string $key_field keyとなる連想配列の添字
	 * @param string $val_field valueとなる連想配列の添字
	 * @return array
	 */
	public static function merge_assoc_key($assoc, $key_field, $val_field = null)
	{
		$output = array_fill_keys(array_column($assoc, $key_field, $key_field), array());

		foreach ($assoc as $elm)
		{
			array_push($output[$elm[$key_field]], $val_field ? $elm[$val_field] : $elm);
		}

		return $output;
	}
}

パフォーマンスがどうか全く分からんですけど、

Arr::merge_assoc_key($input, 'group');
Arr::merge_assoc_key($input, 'group', 'name');

みたいな感じで、期待した結果が得られます。

データベースから取ってきた配列をこんな感じで整形したいことがそこそこある気がします、よね?

書いてて思ったけど、PHPには豊富な配列操作の標準関数が用意されるけども、マニュアルを眺めてあーこれこれ、こんなんあったね、とかやってるあたりまだ未熟だなぁ…

[追記]

LaravelのCollectionクラスにはmapToGroupsというメソッドがあるようです。そうそう、こういうのが欲しかったんだよ。

comments powered by Disqus