PHP array_merge_recursive поведение для целых ключей

Существует ли подход для рекурсивного слияния массивов, так же как и функция PHP array_merge_recursive(), за исключением того, что целочисленные ключи обрабатываются так же, как строковые ключи?

(Для процесса важно, чтобы ключи оставались разборчивыми как целые числа.)

Например:

$a = array(
    'a' => array(1)
);
$b = array(
    'a' => array(2, 3)
);
var_dump(array_merge_recursive($a, $b));

Соединяет ключ "a" и выводит, как ожидалось, следующее:

array(1) {
    ["a"] => array(3) {
        [0] => int(1)
        [1] => int(2)
        [2] => int(3)
    }
}

Однако при использовании целых чисел для ключей (даже если в качестве строки):

$a = array(
    '123' => array(1)
);
$b = array(
    '123' => array(2, 3)
);
var_dump(array_merge_recursive($a, $b));

array_merge_recursive() вернется:

array(2) {
    [0] => array(3) {
        [0] => int(1)
    }
    [1] => array(2) {
        [0] => int(2)
        [1] => int(3)
    }
}

Вместо желаемого:

array(1) {
    ["123"] => array(3) {
        [0] => int(1)
        [1] => int(2)
        [2] => int(3)
    }
}

Мысли?

Ответ 1

вы можете префикс ключей массива с короткой строкой:

function addPrefix($a) {
    return '_' . $a;
}
# transform keys
$array1 = array_combine(array_map('addPrefix', array_keys($array1)), $array1);
$array2 = array_combine(array_map('addPrefix', array_keys($array2)), $array2);
# call array_combine
$array = array_merge_recursive($array1, $array2);
# reverse previous operation  
function stripPrefix($a) {
     return substr($a, 1);
}
$array = array_combine(array_map('stripPrefix', array_keys($array)), $array)     

Ответ 2

Я использую идею soulmerge для преобразования ключей, добавляя строку. Однако моя новая функция может обрабатывать только 2 параметра, но это было так, как вы, так что я пошел. Посмотрите.

// Adds a _ to top level keys of an array
function prefixer($array) {
    $out = array();
    foreach($array as $k => $v) {
        $out['_' . $k] = $v;
    }
    return $out;
}
// Remove first character from all keys of an array
function unprefixer($array) {
    $out = array();
    foreach($array as $k => $v) {
        $newkey = substr($k,1);
        $out[$newkey] = $v;
    }
    return $out;
}
// Combine 2 arrays and preserve the keys
function array_merge_recursive_improved($a, $b) {
    $a = prefixer($a);
    $b = prefixer($b);
    $out = unprefixer(array_merge_recursive($a, $b));
    return $out;
}

И каковы данные образца?

// some sample data    
$a = array(
    '123' => array(1)
);
$b = array(
    '123' => array(2, 3)
);

// what do the results say:    
print_r($a);
// Array
// (
//     [123] => Array
//         (
//             [0] => 1
//         )
// 
// )

print_r($b);
// Array
// (
//     [123] => Array
//         (
//             [0] => 2
//             [1] => 3
//         )
// 
// )

И попробуем их:

print_r(array_merge_recursive($a, $b));
// Array
// (
//     [0] => Array
//         (
//             [0] => 1
//         )
// 
//     [1] => Array
//         (
//             [0] => 2
//             [1] => 3
//         )
// 
// )

print_r(array_merge_recursive_improved($a, $b));
// Array
// (
//     [123] => Array
//         (
//             [0] => 1
//             [1] => 2
//             [2] => 3
//         )
// 
// )

Ответ 3

Если вы хотите, чтобы ключи обрабатывались как строки, просто сделайте так, чтобы строки добавляли префикс, когда вы его заполняете, вместо того, чтобы заполнять его цифрами, а затем пополнять другой массив, чтобы заказать его.

Ответ 4

Эта рекурсивная функция слияния массива не перенумерует целочисленные ключи и добавляет новые значения в существующие, или добавляет новую пару [key = > value], если пара не существует. Я полагаю и уверен, что эта функция такова, что вам нужно.

function array_merge_recursive_adv(array &$array1, $array2) {
        if(!empty($array2) && is_array($array2))
            foreach ($array2 as $key => $value) {
                    if(array_key_exists($key,$array1)) {
                        if(is_array($value)){
                            array_merge_recursive_adv($array1[$key], $value);
                        } else {
                             if(!empty($array1[$key])) {
                                if(is_array($array1[$key])){
                                    array_push($array1[$key], $value);
                                } else {
                                    $array1[$key] = [$array1[$key]];
                                    $array1[$key][] = $value;
                                }
                             } else if(empty($array1[$key])) {
                                $array1[$key] = $value;
                             }
                        }
                    } else {
                        $array1[$key] = $value;
                    }
            }
            return $array1;
    }