各種配列マージの結果の違いと考察 - うえちょこ@ぼろぐ 分室

文字列キーの配列(ハッシュ配列)の例

Variables

$a = array("a" => "apple", "b" => "banana");
$b = array("a" => "pear", "b" => "strawberry", "c" => "cherry");

print_r($a+$b);

Array
(
    [a] => apple
    [b] => banana
    [c] => cherry
)
 $b['a']と$b['b']は同じ文字列キーが存在するので上書きされていない。
 $b['c']は新しい文字列キーなので追加されている。
 この結果から、+演算子の配列マージでは、同じ文字列キーなら上書きされないということがわかる。

print_r(array_merge($a, $b));

Array
(
    [a] => pear
    [b] => strawberry
    [c] => cherry
)
 $b['a']と$b['b']は同じ文字列キーが存在するので上書きしている。
 $b['c']は新しい文字列キーなので追加されている。
 この結果から、array_merge()の配列マージでは、同じ文字列キーなら上書きされるということがわかる。

print_r(array_merge_recursive($a, $b));

Array
(
    [a] => Array
        (
            [0] => apple
            [1] => pear
        )

    [b] => Array
        (
            [0] => banana
            [1] => strawberry
        )

    [c] => cherry
)
 $b['a']と$b['b']は同じ文字列キーが存在するので配列でグループ化されている。
 $b['c']は新しい文字列キーなので追加されている。
 この結果から、array_merge_recursive()の配列マージでは、同じ文字列キーなら配列でグループ化されるということがわかる。

キーに数字が混ざったときの例

Variables

$c = array('peach',
           'grape',
           10  => 'orange',
           'a' => 'apple',
           'b' => 'strawberry');
$d = array('lemon',
           10  => 'kiwi',
           '9' => 'banana',
           '1' => 'cherry',
           'a' => 'pear',
           'c' => 'muscat');

print_r($c+$d);

Array
(
    [0] => peach
    [1] => grape
    [10] => orange
    [a] => apple
    [b] => strawberry
    [9] => banana
    [c] => muscat
)
 $d[0], $d[1], $d[10]は同じ数字キーが存在するので上書きされていない。
 $d['a']は同じ文字列キーが存在するので上書きされていない。
 $c['b']は同じ文字列キーが$dにはないのでそのまま残る。
 $d[9], $d['c']は新しいキーなので追加されている。
 この結果から、+演算子の配列マージでは、同じ文字列キーでも数字キーでも上書きされないということがわかる。
 また、$d['1']のように、数字をクォートした文字列キーであっても、$aに同じ数字のキーがあれば同一のキーとみなしている。

print_r(array_merge($c, $d));

Array
(
    [0] => peach
    [1] => grape
    [2] => orange
    [a] => pear
    [b] => strawberry
    [3] => lemon
    [4] => kiwi
    [5] => banana
    [6] => cherry
    [c] => muscat
)
 $a[0], $a[1], $a[10]は数字キーなので添字が振りなおされている。
 $a['a']は$b['a']によって上書きされている。
 $a['b']は同じ文字列キーが$bにはないのでそのまま残る。
 $b[0], $b['1'], $b['9'], $b[10]は数字キーなので添字が降りなおされた上で追加されている。
 $b['c']は新しい文字列キーなので追加されている。
 この結果から、array_merge()の配列マージでは、数字キーはすべて追加され、添字が振りなおされるということがわかる。
 また、$b['1']のように、数字をクォートした文字列キーであっても、数字キーとみなしている。

print_r(array_merge_recursive($c, $d));

Array
(
    [0] => peach
    [1] => grape
    [2] => orange
    [a] => Array
        (
            [0] => apple
            [1] => pear
        )

    [b] => strawberry
    [3] => lemon
    [4] => kiwi
    [5] => banana
    [6] => cherry
    [c] => muscat
)
 こちらも上記のarray_merge()関数の結果とほぼ同じである。  唯一違うのは、$a['a']と$a['a']は文字列キーなので配列でグループ化されている。
 この結果から、array_merge_recursive()の配列マージでは、数字キーはすべて追加され、添字が振りなおされるが、同じ文字列キーなら配列でグループ化されるということわかる。
 また、$b['1']のように、数字をクォートした文字列キーであっても、数字キーとみなしている。

二次元配列の例

Variables

$e = array('cherry',
           'a' => array('grape', 'a' => 'orange', 'b' => 'lemon'),
           'b' => array('strawberry', 'a' => 'mango'),
            4  => array('egg', 'ham'));
$f = array('kiwi',
           'a' => 'peach',
           'b' => array('muscat', 'a' => 'apple', 'b' => 'banana'),
            4  => array('dog', 5 => 'cat'));

print_r($e+$f);

Array
(
    [0] => cherry
    [a] => Array
        (
            [0] => grape
            [a] => orange
            [b] => lemon
        )

    [b] => Array
        (
            [0] => strawberry
            [a] => mango
        )

    [4] => Array
        (
            [0] => egg
            [1] => ham
        )

)
 +演算子の場合は、値がスカラーであろうと配列であろうと、同じ名前のキーがなければ追加し、あれば何もしない。  よって、今回は何も上書きされていない。

print_r(array_merge($e, $f));

Array
(
    [0] => cherry
    [a] => peach
    [b] => Array
        (
            [0] => muscat
            [a] => apple
            [b] => banana
        )

    [1] => Array
        (
            [0] => egg
            [1] => ham
        )

    [2] => kiwi
    [3] => Array
        (
            [0] => dog
            [5] => cat
        )

)
 array_merge()関数の場合は、値がスカラーであろうと配列であろうと、同じ名前の文字列キーがれば上書きし、なければ追加する。また数字キーは追加された上で添字が振りなおされる

print_r(array_merge_recursive($e, $f));

Array
(
    [0] => cherry
    [a] => Array
        (
            [0] => grape
            [a] => orange
            [b] => lemon
            [1] => peach
        )

    [b] => Array
        (
            [0] => strawberry
            [a] => Array
                (
                    [0] => mango
                    [1] => apple
                )

            [1] => muscat
            [b] => banana
        )

    [1] => Array
        (
            [0] => egg
            [1] => ham
        )

    [2] => kiwi
    [3] => Array
        (
            [0] => dog
            [5] => cat
        )

)
 array_merge_recursive()関数の挙動は説明しにくい。基本的に、値が上書きされて消滅してしまうことはない。数字キーは追加された上で添字が降りなおされるのはarray_merge()関数と一緒だである。文字列キーの場合、グループ化されて配列になる。ただし、文字列キーの値が配列であった場合は、その構造は維持される。これは関数名に「再帰」と書いてあるからも想像できる。
 説明しにくいので元の値と結果を見比べて、その性質をつかんでほしい。