結論
function array_multi_columns(array $array, array $index_keys){
return array_map(fn(...$row) => array_combine($index_keys, $row), ...array_map(fn($key) => array_column($array, $key), $index_keys));
}
1行で短く美しく書きたかったのでこうしました。
解説
取り出したい列名のデータを取り出し
array_map(fn($key) => array_column($array, $key), $index_keys))
「列を取り出す」という操作は、php純正関数であるarray_columnを使います。
foreachなどを使うとarray_columnの内部の最適化の恩恵を受けられないためです。
zip操作
return array_map(fn(...$row) => array_combine($index_keys, $row), ...array_map(...));
array_mapに複数配列を渡すとzip操作になります。
普通にzipすると列名キーが消えてしまうので、array_combineでキーを振り直してやります。
(参考:https://www.php.net/manual/ja/function.array-map.php)
パフォーマンス比較
同じ操作の比較として、array_filterを使うやり方も考えられます。
コードは示しませんが、in_arrayやarray_flip+issetを使ってキーを検索することになります。
しかしその場合、in_arrayやissetに、各列のキーを一つ一つ渡す必要があるため、元配列の行数×元配列の列数ぶん、(in_arrayないしissetを内部実装した)自作クロージャを実行することになります。
しかし今回の実装であれば、自作クロージャの呼び出し回数は、取り出す列数+元の配列の行数となり、ループが必要な処理をphpの内部関数に委託することができます。php内部関数は高度に最適化されているため、列の絞り込みを自作クロージャで実装するよりも遥かに高速に動作します。