如何创建一个递归函数来取消PHP中的多维数组?

时间:2018-01-12 15:18:47

标签: php arrays recursion

下面是我的目标数组,我希望根据候选数组元素按键取消其元素。

$target = [
    60 => "Home"
    "Villa" => [
        "30" => "Vi",
    ],
    70 => "A",
    40 => "B",
    50 => "C",
    "Land" => [
        1 => "La",
        35 => "Lb",
        37 => "Lc",
        39 => "Ld",
    ],
];

$candidate = [30, 50, 35, 37];

以下是取消设置后我想要的结果。

$target = [
    60 => "Home"
    70 => "A",
    40 => "B",
    "Land" => [
        1 => "La",
        39 => "Ld",
    ],
];

'别墅'也必须消失,因为它的元素" 30" => "六"一直未设置。

在我的for-loop解决方案之下。

foreach ($target as $id => $option) {
    if (isset($candidate[$id])) {
      unset($target[$id]);
    }
    elseif (is_array($option)) {
      foreach ($option as $sub_id => $opt) {
        if (isset($candidate[$sub_id])) {
          unset($target[$id][$sub_id]);
        }
      }
    }

    if (!count($target[$id])) {
      unset($target[$id]);
    }
}

如何在递归解决方案中替换此for循环?

3 个答案:

答案 0 :(得分:3)

function del($target, $candidate) {
    foreach ($target as $key => $value) {
        if (in_array($key, $candidate)) {
            unset($target[$key]);
        } elseif (is_array($value)) {
            $target[$key] = del($value, $candidate);
            if (!count($target[$key])) {
                unset($target[$key]);
            }
        }
    }
    return $target;
}

$new = del($target, $candidate);
var_dump($new);

答案 1 :(得分:3)

这开头是对Mehdi回答的评论,但我的空间不足了:

虽然我认为数组是通过引用传递的,并且应该有最小的开销来分配对它来自的变量的引用,但是我明白通过引用显式传递可能更健壮和透明。

function clean(&$target, $candidate, $depth=0){
   if (++$depth>10) {
      // erk!
      trigger_error("Too deep!");
   }
   // Loop through candidates
   foreach($candidate as $index){
       // If the value is an array
       if(isset($target[$index]) && is_array($target[$index])){
           clean($target[$index], $candidate, $depth);
           if (!count($target[$index])) unset($target[$index]); // thanks jhilgeman
       } else {
           isset($target[$index]) && unset($target[$index]);
       }
   }
}

clean($target, $candidate);
var_dump($target);

答案 2 :(得分:1)

修改

<?php
$target = [
    60 => "Home",
    "Villa" => [
        "30" => "Vi",
    ],
    70 => "A",
    40 => "B",
    50 => "C",
    "Land" => [
        1 => "La",
        35 => "Lb",
        37 => "Lc",
        39 => "Ld",
    ],
];

$candidate = [30, 50, 35, 37];

function clean(&$target, $candidate){
    // Loop through target
    foreach($target as $index => $value){
        // If the value is an array
        if(is_array($value)){
            // Clean it first
            $result = clean($value, $candidate);
            $target[$index] = $result;
        } else {
            // Check if the key is in the candidate array
            if(in_array($index, $candidate)){
                $target[$index] = NULL;
            }
        }
        // If the value is empty
        if(empty($target[$index])){
            // Unset it
            unset($target[$index]);
        }
    }
}

$target = clean($target, $candidate);

var_dump($target);

结果:

/var/www/test.php:47:
array (size=4)
  60 => string 'Home' (length=4)
  70 => string 'A' (length=1)
  40 => string 'B' (length=1)
  'Land' => 
    array (size=2)
      1 => string 'La' (length=2)
      39 => string 'Ld' (length=2)

正如 symcbean 提到的那样使用引用会更好