Я ищу способ рекурсивного удаления частей массива и его дочерних элементов путем проверки только ключей.
В приведенном ниже примере $ array является входным массивом, а $ remove содержит ключи, которые должны быть удалены из $ array:
$array = [
'key1' => [
'key11' => [],
'key12' => [
'key121' => [],
'key122' => [],
'key123' => [],
],
'key13' => [],
],
'key2' => [
'key21' => [],
'key22' => [],
'key23' => [],
'key24' => [],
'key25' => [
'key251' => [
'key2511' => [],
'key2512' => [],
'key2513' => [],
'key2514' => [],
'key2515' => [],
],
'key252' => [
'key2521' => [],
'key2522' => [],
'key2523' => [],
'key2524' => [],
'key2525' => [],
],
],
],
'key3' => [
'key31' => [],
'key32' => [],
'key33' => [],
'key34' => [],
'key35' => [
'key351' => [
'key3511' => [],
'key3512' => [],
'key3513' => [],
'key3514' => [],
'key3515' => [],
],
],
],
];
$remove = [
'key1' => [
'key12' => [
'key121' => [],
],
'key13' => [],
],
'key2' => [
'key25' => [
'key251' => [
'key2514' => [
],
],
'key252' => [],
],
],
'key3' => [],
];
Я написал уродливый и нерекурсивный алгоритм:
foreach ($array as $k1 => $v1) {
foreach ($v1 as $k2 => $v2) {
foreach ($v2 as $k3 => $v3) {
foreach ($v3 as $k4 => $v4) {
if (isset($array[$k1][$k2][$k3][$k4]) && isset($remove[$k1][$k2][$k3][$k4]) && 0 === count($remove[$k1][$k2][$k3][$k4])) {
unset($array[$k1][$k2][$k3][$k4]);
}
}
if (isset($array[$k1][$k2][$k3]) && isset($remove[$k1][$k2][$k3]) && 0 === count($remove[$k1][$k2][$k3])) {
unset($array[$k1][$k2][$k3]);
}
}
if (isset($array[$k1][$k2]) && isset($remove[$k1][$k2]) && 0 === count($remove[$k1][$k2])) {
unset($array[$k1][$k2]);
}
}
if (isset($array[$k1]) && isset($remove[$k1]) && 0 === count($remove[$k1])) {
unset($array[$k1]);
}
}
var_dump($array);
Он возвращает вывод, который я ищу:
array(2) {
["key1"]=>
array(2) {
["key11"]=>
array(0) {
}
["key12"]=>
array(2) {
["key122"]=>
array(0) {
}
["key123"]=>
array(0) {
}
}
}
["key2"]=>
array(5) {
["key21"]=>
array(0) {
}
["key22"]=>
array(0) {
}
["key23"]=>
array(0) {
}
["key24"]=>
array(0) {
}
["key25"]=>
array(1) {
["key251"]=>
array(4) {
["key2511"]=>
array(0) {
}
["key2512"]=>
array(0) {
}
["key2513"]=>
array(0) {
}
["key2515"]=>
array(0) {
}
}
}
}
}
У меня вопрос, как я могу сделать эту функциональность рекурсивной, так как теоретически $ array может быть вложена бесконечно?
Любая помощь будет принята с благодарностью. Спасибо!
А пока я придумал альтернативное решение:
function array_remove_key_recursive($input, $remove)
{
$ret = [];
foreach ($input as $key => $value) {
if (array_key_exists($key, $remove)) {
if (is_array($value)) {
if (count($remove[$key]) > 0) {
$diff_recursive = array_remove_key_recursive($value, $remove[$key]);
if (count($diff_recursive) > 0) {
$ret[$key] = $diff_recursive;
}
}
} else {
if ($value != $remove[$key]) {
$ret[$key] = $value;
}
}
} else {
$ret[$key] = $value;
}
}
return $ret;
}
Вот как бы я это сделал
function test (&$arr, $remove) {
$keys =array_keys ($remove, [], true) ;
$arr =array_filter ($arr, function ($v, $k) use ($remove, $keys) {
return !in_array ($k, $keys, true) ;
},
ARRAY_FILTER_USE_BOTH
) ;
$keys =array_diff (array_keys ($remove), $keys) ;
foreach ( $keys as $key )
test ($arr [$key], $remove [$key]) ;
}
test ($array, $remove) ;
print_r ($array) ;
Это функция, которая рекурсивно делает то, что вам нужно.
function remove_by_keys(array $array, array $remove)
{
// Copy the input array into the result; will remove parts of it
// according to the information stored in $remove
$result = $array;
// Check the keys to remove
foreach ($remove as $key => $value) {
if ($value === []) {
// Remove the key and the entire value associated with the key
unset($result[$key]);
} else {
// Keep the key, recursively remove parts of the value (next level)
$result[$key] = remove_by_keys($array[$key], $remove[$key]);
}
}
return $result;
}
Как это устроено:
Функция получает два параметра: $array
это входной массив, $remove
список ключей (и вложенных клавиш), которые необходимо удалить из $array
,
Создает копию входного массива, затем анализирует ключи ($key
) и значения $remove
, Если значение []
(пустой массив), затем соответствующий ключ и значение $array
полностью удалены из результата. Если $remove[$key]
не является []
тогда функция рекурсивно вызывается для $array[$key]
а также $remove[$key]
(следующий уровень) и значение, которое он возвращает (отфильтрованный $array[$key]
) хранится в массиве результатов по ключу $key
,