PHPの多次元連想配列をマージする
この記事は次のブログに引っ越しました。
一般的に配列のマージ(結合)は"+"(プラス)を使うのが一番簡単だったりするのですが、一部のキー(添え字)が同じ(ダブり)配列を結合する場合に、いささか問題がおきるケースがあります。
array_merge_recursive()関数や array_diff_assoc()関数でも、思い通りに結合できない方は、この関数を試してみてください。
php function fArray_merge( $aOld, $aNew ){ if( is_array( $aOld ) ){if( is_array( $aNew ) ){ foreach( $aNew as $sKey => $mValue ){ if( isset( $aOld[$sKey] ) && is_array( $mValue ) && is_array( $aOld[$sKey] ) ){ $aOld[$sKey] = fArray_merge( $aOld[$sKey], $mValue ); } else { $aOld[$sKey] = $mValue; } } } } elseif( ! is_array( $aOld ) && ( strlen( $aOld ) == 0 || $aOld == 0 ) ){ $aOld = $aNew; } return( $aOld );}
所感
私は、配列データの更新をする際に、配列をマージすることをよくやります。
たとえば、すべてのデータの入った配列があったとして、それに更新したい配列データだけを渡せば(マージさせれば)更新される感じです。
具体的には、下記のような添え字付きの配列(連想配列)データがあったとして、そのうちの1部を更新したり追加したい場合に、添え字を気にせず更新できて便利です。
特に複数フォームなどから受け取って更新する時など、どのフィールド(添え字のデータ)が更新されるかわからない場合に重宝します。
配列の結合(マージ)時、空要素のみ追加するか //元のデータ $aData_old = array( 'data1' => 'uno', 'data2' => 'dos', 'data3' => 'tres',); //更新したいデータ $aData_new = array( 'data2' => 'TWO', 'data4' => 'FOUR',); //更新 $aData1 = $aData_new + $aData_old; $aData2 = $aData_old + $aData_new; 上記の結果($aDataの中身)は、このようになります。 //$aData1 = $aData_new + $aData_old; array( 'data1' => 'uno', 'data2' => 'TWO', 'data3' => 'tres', 'data4' => 'FOUR',) //$aData2 = $aData_old + $aData_new; array( 'data1' => 'uno', 'data2' => 'dos', 'data3' => 'tres', 'data4' => 'FOUR', )"+"(プラス)の前後に注意してください。"$a+$b"と"$b+$a"では答えが異なるんです。
上書きするのではなく、前者の配列にない(足りない)添え字のデータを後者の配列で補間(MIX)する感じです。
これにより、更新したいデータ(新しいデータ)に古い全体データを足すと、更新されていないデータが加わり、更新されるという理屈です。
問題は、これが多次元になった場合なんです。
どうも、ルートの添え字というか最初の添え字しかチェックしないようで、多次元配列の下の層を更新したい場合には使えないんです。
//元のデータ $aData_old = array( 'city' => array( 'japan' => 'Tokyo', 'mexico' => 'Mexico D.F.', 'korea' => 'Seoul', ),); //更新したいデータ$aData_new = array( 'city' => array( 'japan' => '東京', ),); //NGな更新 $aData = $aData_new + $aData_old;
上記でうまくマージできそうなもんですが、実はうまくいかないんです。
結果はこんな感じ
$aDataの中身 array( 'city' => array( 'japan' => '東京' ))どうも1次元目までしか添え字をチェックしないようなんですな。で、冒頭のような関数が必要になったわけです。