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次元目までしか添え字をチェックしないようなんですな。で、冒頭のような関数が必要になったわけです。