PHP: проблема с объединением массивов

ОК, у меня есть эта функция (я получил ответ на этот вопрос), которая объединяет массив следующим образом:

Функции

function readArray( $arr, $k, $default = 0 ) {
    return isset( $arr[$k] ) ? $arr[$k] : $default ;
}

function merge( $arr1, $arr2 ) {
    $result = array() ;
    foreach( $arr1 as $k => $v ) {
        if( is_numeric( $v ) ) {
            $result[$k] = (int)$v + (int) readArray( $arr2, $k ) ;
        } else {
            $result[$k] = merge( $v, readArray($arr2, $k, array()) ) ;
        }
    }
    return $result ;
}

Применение

$basketA = array( "fruit" => array(), "drink" => array() ) ;
$basketA['fruit']['apple'] = 1;
$basketA['fruit']['orange'] = 2;
$basketA['fruit']['banana'] = 3;
$basketA['drink']['soda'] = 4;
$basketA['drink']['milk'] = 5;

$basketB = array( "fruit" => array(), "drink" => array() ) ;
$basketB['fruit']['apple'] = 2;
$basketB['fruit']['orange'] = 2;
$basketB['fruit']['banana'] = 2;
$basketB['drink']['soda'] = 2;
$basketB['drink']['milk'] = 2;

$basketC = merge( $basketA, $basketB ) ;
print_r( $basketC ) ;

Выход

Array
(
    [fruit] => Array
        (
            [apple] => 3
            [orange] => 4
            [banana] => 5
        )

    [drink] => Array
        (
            [soda] => 6
            [milk] => 7
        )

)

Хорошо, это работает с 1 ошибкой, которую я не могу понять, как исправить: если в $arr1 отсутствует что-то, что есть в $arr2, он должен просто использовать значение из $arr2, но вместо этого опускает все это вместе:

Пример

$basketA = array( "fruit" => array(), "drink" => array() ) ;
$basketA['fruit']['apple'] = 1;
$basketA['fruit']['orange'] = 2;
$basketA['fruit']['banana'] = 3;
$basketA['drink']['milk'] = 5;

$basketB = array( "fruit" => array(), "drink" => array() ) ;
$basketB['fruit']['apple'] = 2;
$basketB['fruit']['orange'] = 2;
$basketB['fruit']['banana'] = 2;
$basketB['drink']['soda'] = 2;
$basketB['drink']['milk'] = 2;

$basketC = merge( $basketA, $basketB ) ;
print_r( $basketC ) ;

Выход

Array
(
    [fruit] => Array
        (
            [apple] => 3
            [orange] => 4
            [banana] => 5
        )

    [drink] => Array
        (
            [milk] => 7
        )

)

Обратите внимание, что [soda] нет в новом массиве, потому что его не было в первом массиве.

Как я могу это исправить???

Спасибо!!!


person JD Isaacks    schedule 22.01.2010    source источник


Ответы (1)


Быстрое исправление, измените функцию merge(), чтобы она выглядела так:

function merge( $arr1, $arr2 ) {
    $result = array() ;
    foreach( $arr1 as $k => $v ) {
        if( is_numeric( $v ) ) {
            $result[$k] = (int)$v + (int) readArray( $arr2, $k ) ;
        } else {
            $result[$k] = merge( $v, readArray($arr2, $k, array()) ) ;
        }
    }
    foreach( $arr2 as $k => $v ) {
        if( is_numeric( $v ) ) {
            $result[$k] = (int)$v + (int) readArray( $arr1, $k ) ;
        } else {
            $result[$k] = merge( $v, readArray($arr1, $k, array()) ) ;
        }
    }
    return $result ;
}

Выход:

Array
(
    [fruit] => Array
        (
            [apple] => 3
            [orange] => 4
            [banana] => 5
        )

    [drink] => Array
        (
            [soda] => 2
            [milk] => 7
        )
)

Стоит также отметить, что один только array_merge_recursive() делает почти то же самое:

$basketC = array_merge_recursive($basketA, $basketB);

Выход:

Array
(
    [fruit] => Array
        (
            [apple] => Array
                (
                    [0] => 1
                    [1] => 2
                )

            [orange] => Array
                (
                    [0] => 2
                    [1] => 2
                )

            [banana] => Array
                (
                    [0] => 3
                    [1] => 2
                )

        )

    [drink] => Array
        (
            [milk] => Array
                (
                    [0] => 5
                    [1] => 2
                )

            [soda] => 2
        )
)

Поэтому, если вы хотите узнать, сколько апельсинов в $basketC, вам просто нужно сделать следующее:

array_sum($basketC['fruit']['orange']); // 4

Таким образом, вам не нужно использовать какие-либо хакерские, медленные и непроверенные пользовательские функции.

person Alix Axel    schedule 22.01.2010
comment
Это работает, хотя я удивлен, глядя на код, я бы подумал, что он объединяет их дважды, что приводит к удвоению значений, но я протестировал его, и он работает так, как должен. Спасибо!! - person JD Isaacks; 22.01.2010