dotdx80642
2018-01-12 15:18
浏览 52
已采纳

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

Below is my target array which I would like to unset its elements by key based on the candidate array element.

$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];

Below is the result that I want after unsetting.

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

'Villa' must also be gone because it's empty after it's element "30" => "Vi" has been unset.

Below my solution in 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]);
    }
}

How can I replace this for-loop in a recursive solution?

  • 写回答
  • 好问题 提建议
  • 关注问题
  • 收藏
  • 邀请回答

3条回答 默认 最新

  • dqrsceg6279196 2018-01-12 15:42
    已采纳
    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);
    
    已采纳该答案
    评论
    解决 无用
    打赏 举报
  • douyuliu9527 2018-01-12 15:34

    EDIT:

    <?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);
    

    Result:

    /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)
    

    As symcbean mentioned using reference here would be better

    评论
    解决 无用
    打赏 举报
  • douxie9471 2018-01-12 15:44

    This started as a comment on Mehdi's answer, but I ran out of space:

    While I believe arrays are passed by reference, and there should be minimal overhead assigning the reference to the variable it came from, it strikes me that explicitly passing by reference might be more robust and transparent.

    i.e.

    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);
    
    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题