【PHP】多次元連想配列から特定キーの値を取得する方法
更新日:2023/03/19
PHPで、多次元の連想配列から特定のキーを探して、その値を取得する方法を調べてみました。
array_column()を使う
ネットで多次元連想配列から特定キーの値を取得する方法を調べてみました。
array_column()という便利な関数があると書いてあったので、使ってみます。
$aray = [
[ 'id' => 'A' , 'value' => 1 , 'option' => 'a'],
[ 'id' => 'B' , 'value' => 2 ],
[ 'id' => 'C' , 'value' => 3 , 'option' => 'c'],
];
var_dump( array_column($aray,'option'));
// 結果
// Array
// (
// [0] => a
// [1] => c
// )
上手く値を取得できました。
元の位置を特定したいときは、他のキーをインデックスとして使用できます。
var_dump( array_column($aray,'option','id'));
// 結果
// Array
// (
// [A] => a
// [C] => c
// )
なんだかモヤモヤしますが、便利ですね。
array_column()は2次元配列な件
前項の例は、2次元配列です。
array_column()のリファレンスを見ると、第一パラメーターは多次元配列と書いてあります。
なので3次元でも、4次元でもキーを探してくれるはずですね。
やってみます。
$aray = [
[ 'id' => 'A' , 'value' => 1 , 'option' => 'a'],
[ 'id' => 'B' , 'value' => 2 ,
'data' => [ 'option' => 'b' ]
],
[ 'id' => 'C' , 'value' => 3 , 'option' => 'c'],
];
print_r( array_column($aray,'option','id'));
// 結果
// Array
// (
// [A] => a
// [C] => c
// )
ダメでした。
2次元までしか見てないですね。
PHPの多次元配列は、2次元のみを指すのでしょうか。
わかりません...
結局総当たりな件
他に便利な関数がないか調べたけれど、見つけることができませんでした。
仕方が無いので、ループで総当たりします。
function get_array_all_key_value( $aray , $key , $is_regex=false , $is_key_add=false ){
$result =[];
foreach( $aray as $index => $value ){
if( ($is_regex === false && $index === $key)
|| ($is_regex === true && preg_match( $key , $index , $matches) ===1) )
$result[] = $is_key_add ? array( 'key' => $index, 'value' => $value ,'hierarchy'=>[]) : $value;
elseif( is_array($value) ) {
$res = get_array_all_key_value( $value , $key , $is_regex , $is_key_add);
if( $is_key_add ){
foreach( $res as &$r ){
array_unshift( $r['hierarchy'] , $index );
}
}
$result = array_merge( $result, $res );
}
}
return $result;
}
この関数を使って、テストしてみます。
$aray = [
[ 'id' => 'A' , 'value' => 1 , 'option' => 'a'],
[ 'id' => 'B' , 'value' => 2 ,
'data' => [ 'option' => 'あたり!' ]
],
[ 'id' => 'C' , 'value' => 3 , 'option' => 'c'],
[ 'id' => 'D' , 'value' => 4 ,
'data1' => [ 'option' => [] ],
'data22' => [ 'data' => [ 'option' => 'あたり!!' ] ],
],
];
print_r( get_array_all_key_value($aray,'option') );
// Array
// (
// [0] => a
// [1] => あたり!
// [2] => c
// [3] => Array()
// [4] => あたり!!
// )
上手く抽出できていますね。
おまけ機能で、正規表現での検索もできます。
print_r( get_array_all_key_value($aray,'#^data\d*$#' , true) );
// Array
// (
// [0] => Array ( [option] => あたり! )
// [1] => Array ( [option] => Array ( ) )
// [2] => Array ( [data] => Array ( [option] => あたり!!) )
// )
さらにおまけで、結果にキーと階層を含むこともできます。
print_r( get_array_all_key_value( $aray , 'option' ,false ,true));
// Array
// (
// [0] => Array(
// [key] => option
// [value] => a
// [hierarchy] => Array([0] => 0)
// )
// [1] => Array(
// [key] => option
// [value] => あたり!
// [hierarchy] => Array(
// [0] => 1
// [1] => data
// )
// )
// [2] => Array(
// [key] => option
// [value] => c
// [hierarchy] => Array(
// [0] => 2
// )
// )
// [3] => Array(
// [key] => option
// [value] => Array()
// [hierarchy] => Array(
// [0] => 3
// [1] => data1
// )
// )
// [4] => Array(
// [key] => option
// [value] => あたり!!
// [hierarchy] => Array(
// [0] => 3
// [1] => data22
// [2] => data
// )
// )
// )
応用1:多次元配列から特定のキー階層を持つ値を取得する
単一のキーではなくて、特定のキー階層を追って値を抽出します。
function get_array_all_find_hierarchy_key_value( $aray , $keys , $regx_flg=false , $is_key_add=false ,$depth=0){
$keys = (array)$keys;
$regflg = ($regx_flg===true || (is_array($regx_flg) && in_array($depth,$regx_flg)))
? true : false;
$key_values = get_array_all_key_value($aray,$keys[$depth],$regflg, $is_key_add);
if( count($keys) === ++$depth ) return $key_values;
$result = [];
foreach( $key_values as $key_value ){
$value = $is_key_add ? $key_value['value'] : $key_value;
if( !is_array( $value ) )continue;
$ress = get_array_all_find_hierarchy_key_value($value,$keys,$regx_flg,$is_key_add,$depth);
foreach( $ress as &$res ){
if( $is_key_add === true )
$res['hierarchy'] = [...$key_value['hierarchy'],$key_value['key'],...$res['hierarchy']];
$result[] = $res;
}
}
return $result;
}
まずは1階層目のキーで値を抽出します。
次に抽出した値から、配列だけを抜き出します。
抜き出した配列から、次の階層のキーで値を抽出します。
これの繰り返しです。
ただ、前項のおまけにも対応したら、途端に面倒なコードになりました。
テストしてみます。
次の例は、キー階層が'data'→'option'の値を列挙しています。
$aray = [
[ 'id' => 'A' , 'value' => 1 , 'option' => 'a'],
[ 'id' => 'B' , 'value' => 2 ,
'data' => [ 'option' => 'あたり!' ]
],
[ 'id' => 'C' , 'value' => 3 , 'option' => 'c'],
[ 'id' => 'D' , 'value' => 4 ,
'data1' => [ 'option' => [] ],
'data2' => [ 'data' => [ 'option' => 'あたり!!' ] ],
],
];
print_r(
get_array_all_find_hierarchy_key_value(
$aray,array('data','option')
));
// Array
// (
// [0] => あたり!
// [1] => あたり!!
// )
2番目の引数は、配列でなくても動作します。
print_r( get_array_all_find_hierarchy_key_value($aray,'option' ));
// Array
// (
// [0] => a
// [1] => あたり!
// [2] => c
// [3] => Array()
// [4] => あたり!!
// )
キーや階層の取得もできます。
print_r( get_array_all_find_hierarchy_key_value($aray,array('#^data\d*$#','option'),[0],true));
// Array
// (
// [0] => Array (
// [key] => option
// [value] => あたり!
// [hierarchy] => Array (
// [0] => 1
// [1] => data
// )
// )
// [1] => Array (
// [key] => option
// [value] => Array( )
// [hierarchy] => Array (
// [0] => 3
// [1] => data1
// )
// )
// [2] => Array (
// [key] => option
// [value] => あたり!!
// [hierarchy] => Array (
// [0] => 3
// [1] => data22
// [2] => data
// )
// )
// )
応用2:多次元配列から特定のキー値を持つ配列を取得する
多次元の連想配列から、特定のキーに特定の値を持つ配列を取得するケースもあります。
この場合は、次のようなコードになります。
function get_array_all_find_key_value( $aray , $key , $value ){
$result =[];
if( array_key_exists($key,$aray) && $aray[$key] === $value )
$result[] = $aray;
foreach( $aray as $v ){
if( is_array($v) )
$result = array_merge( $result,
get_array_all_find_key_value( $v , $key ,$value));
}
return $result;
}
都合により、階層の取得や正規表現は対応していません。
関数の使用例は、次のようになります。
値が'a'の'option'キーを含む配列を列挙します。
$aray = [
[ 'id' => 'A' , 'value' => 1 , 'option' => 'a'],
[ 'id' => 'B' , 'value' => 2 ,
'data' => [ 'option' => 'b' ]
],
[ 'id' => 'C' , 'value' => 3 , 'option' => 'c'],
[ 'id' => 'D' , 'value' => 4 ,
'data1' => [ 'option' => [] ],
'data2' => [ 'data' => [ 'option' => 'a' ] ],
],
];
print_r( get_array_all_find_key_value($aray,'option','a') );
// Array
// (
// [0] => Array
// (
// [id] => A
// [value] => 1
// [option] => a
// )
// [1] => Array
// (
// [option] => a
// )
// )
とりあえず、以上です。
更新日:2023/03/19
関連記事
スポンサーリンク
記事の内容について
こんにちはけーちゃんです。
説明するのって難しいですね。
「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。
裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。
掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。
ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php
このサイトは、リンクフリーです。大歓迎です。