array_column について
PHPのarray_column
は,多次元配列から単一のカラムの値を返してくれる,とても便利な関数です。
// このような多次元配列から…$array=[2=>['id'=>111,'name'=>'suzuki','age'=>21],3=>['id'=>222,'name'=>'sato','age'=>34],5=>['id'=>333,'name'=>'tanaka','age'=>55],];// 単一のカラム値の配列を作れるvar_export(array_column($array,'name'));// array (// 0 => 'suzuki',// 1 => 'sato',// 2 => 'tanaka',// )
しかしながら,返り値の配列のキーは
- 第3引数を指定しない場合:単純に0から振り直される
- 第3引数を指定した場合 :指定カラムの値がキーとして使われる
のどちらかで,元の配列のキー(上の例だと「2」「3」「5」)は維持されません。
元の配列のキーを維持したいとき
次の3通りの方法を紹介します。
- 方法①
array_column
と他の関数を組み合わせる - 方法②
array_map
を使う - 方法③
foreach
を使う
※2020/10/14 当記事の初投稿時には方法①のみを紹介していたのですが,コメント欄で@tadsanさんに教えていただいた方法②に加えて,foreachを使う場合の方法③も追加しました。また,まとめの内容を変更し,array_column
についての蛇足も追記しました。
方法①array_column
と他の関数を組み合わせる
array_keys
で元の配列のキーを取得し,第3引数を指定しないarray_column
の返り値と合体させましょう。対応する配列の生成にはarray_combine
を使います。
$array=[2=>['id'=>111,'name'=>'suzuki','age'=>21],3=>['id'=>222,'name'=>'sato','age'=>34],5=>['id'=>333,'name'=>'tanaka','age'=>55],];// キーを配列として取得$keys=array_keys($array);// => [ 2, 3, 5 ]// 指定要素を配列として取得$values=array_column($array,'name');// => [ 'suzuki', 'sato', 'tanaka' ]// それぞれの配列を合体$combined=array_combine($keys,$values);// 出力var_export($combined);// array (// 2 => 'suzuki',// 3 => 'sato',// 5 => 'tanaka',// )
上記の操作を1行で書くと以下のようになります。
array_combine(array_keys($array),array_column($array,'name'));
- メリット :関数の使い方として何をやっているかは分かりやすい
- デメリット:関数の呼び出しが多い
方法②array_map
を使う
「array_column
を使いたい」という記事なのにタイトル詐欺もいいとこですが,こちらの方が簡潔に記述できます(コメント欄で@tadsanさんに教えていただきました)。
$array=[2=>['id'=>111,'name'=>'suzuki','age'=>21],3=>['id'=>222,'name'=>'sato','age'=>34],5=>['id'=>333,'name'=>'tanaka','age'=>55],];var_dump(array_map(fn($a)=>$a['name'],$array));
上記のコードの配列操作部分を抜き出すと以下のようになります。
array_map(fn($a)=>$a['name'],$array);
array_map
の第1引数のfn($a) => $a['name']
の部分がPHP7.4で導入された「アロー関数」なので,7.4より前の環境では「無名関数」を使って置き換えることになります。
array_map(function($a){return$a['name'];},$array);
- メリット :アロー関数が使える環境では簡潔に記述できる
- デメリット:ワンライナーで無名関数を使う場合には少し可読性が下がる
方法③foreach
を使う
「foreach
を使わずに済むようにarray_column
があるのでは?」と言われればそれまでなのですが,方法②でarray_column
を使わなかったので一応。
$array=[2=>['id'=>111,'name'=>'suzuki','age'=>21],3=>['id'=>222,'name'=>'sato','age'=>34],5=>['id'=>333,'name'=>'tanaka','age'=>55],];$result=[];foreach($arrayas$key=>$values){$result[$key]=$values['name'];}var_export($result);// array (// 2 => 'suzuki',// 3 => 'sato',// 5 => 'tanaka',// )
- メリット :一見して何をやっているか分かりやすい
- デメリット:一時変数が必要,コードも複数行にわたる
まとめ
方法②のarray_map
とアロー関数を使ったワンライナーが一番タイプ数も少なくおすすめです。思想信条上の理由でクロージャを使いたくない方は,
- 1行にまとめたければ方法①
- だれが見ても分かりやすいコードにしたければ方法③
が良いと思います。記事タイトルにそぐわない結論になってしまいましたが。
蛇足
array_column
はPHP5.5から導入された関数ですが,よくよく調べてみると「第3引数が未指定の場合に元配列のキーを維持する案」がリリース前に出ており,実際にプルリクエストも出されていたみたいですが,議論の末に見送られた経緯があるようです。こんな記事を書いといてアレですが,元配列のキーを維持したくない場合の方が多いはずなので,これは見送られて良かったと思われます。
それとは別に,「第3引数に true が指定された場合に元配列のキーを維持する案」もあったようで,この案についてはリリース後もたまにリクエストがあがっているみたいです(PHPで実装された array_column リポジトリの issue とか)。
ただ,PHP公式サイト上のこのページ(←何故かつながりづらい)では,「第3引数に true を指定する案」や「第4引数を追加する案」などのいかなる変更も既存の予想される動作を破壊し得るとして,array_column
の実装者である ramsey さん自身がリクエストを close しており,キーを維持するための機能追加が行われることは今後まず無さそうです。
参考
array_column
の公式ページに「第3引数に -1 を渡すと元の配列のキーを維持する関数」が掲載されています。この関数をコピペして使えば,array_column_ext( $array,'name', -1 )
のように簡潔な記述ができます(どんな場合でも使えるかどうかは検証してないので分かりません)。 ↩