Есть ли подход для рекурсивного слияния массивов, так же, как это array_merge_recursive()
функция array_merge_recursive()
PHP, за исключением того, что целочисленные ключи обрабатываются так же, как и строковые ключи?
(Для процесса важно, чтобы ключи оставались разборчивыми как целые числа.)
Например:
$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) } }
Мысли?
вы можете префикс ключей массива с короткой строкой:
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)
Я использую идею 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 // ) // // )
Если вы хотите, чтобы ключи обрабатывались как строки, просто сделайте так, чтобы строки добавляли префикс, когда вы его заполняли, вместо того, чтобы заполнять его цифрами, а затем пополнять другой массив только для его заказа.
Эта функция рекурсивного слияния не перенумерует целочисленные ключи и добавляет новые значения к существующим ИЛИ добавляет новую пару [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; }