Search code examples
phprecursionmultidimensional-arrayfilterarray-unset

Removing arrays from multi dimension array based on single values


I am trying to filter a multi-dimension array by removing subarrays where the permission value is no.

My array:

$array = array(
    array(
        'name' => 'dashboard',
        'permission' => 'yes'
    ),
    array(
        'name' => 'Purchase Orders',
        'permission' => 'yes',
        'dropdown' => array(
            array(
                'name' => 'View Complete',
                'permission' => 'yes'
            ),
            array(
                'name' => 'New PO',
                'permission' => 'no'
            )
        )
    ),
    array(
        'name' => 'dashboard',
        'permission' => 'no'
    )
);

This is my desired result: (notice all groups with permission=>'no' have been fully removed)

$array = array(
    array(
        'name' => 'dashboard',
        'permission' => 'yes'
    ),
    array(
        'name' => 'Purchase Orders',
        'permission' => 'yes',
        'dropdown' => array(
            array(
                'name' => 'View Complete',
                'permission' => 'yes'
            )
        )
    )
);

Using array_filter() with a callback function does this very simply on the first level, but I cannot work out a simple solution for doing it on every level.

At the moment my solution is looping and unsetting each key, but it needs to know the exact structure of the array and feels quite messy.


Solution

  • Here is a method with recursion. A few inline comments to help explain, but there isn't much to explain that the basic functions don't express inherently.

    Code: (Demo)

    $array = array(
    array(
        'name' => 'dashboard',
        'permission' => 'yes'
    ),
    array(
        'name' => 'Purchase Orders',
        'permission' => 'yes',
        'dropdown' => array(
            array(
                'name' => 'View Complete',
                'permission' => 'yes'
            ),
            array(
                'name' => 'New PO',
                'permission' => 'no'
            )
        )
    ),
    array(
        'name' => 'dashboard',
        'permission' => 'no'
    ));
    
    function recursive_filter($array){
        foreach($array as $k=>&$subarray){  // make modifiable by reference
            if(isset($subarray['permission']) && $subarray['permission']=='no'){ // check that this element exists before trying to access it
                unset($array[$k]);  // remove subarray
            }elseif(isset($subarray['dropdown'])){  // check that this element exists before trying to access it
                $subarray['dropdown']=recursive_filter($subarray['dropdown']);  // recurse
            }
        }
        return $array;
    }
    
    var_export(recursive_filter($array));
    

    Output:

    array (
      0 => 
      array (
        'name' => 'dashboard',
        'permission' => 'yes',
      ),
      1 => 
      array (
        'name' => 'Purchase Orders',
        'permission' => 'yes',
        'dropdown' => 
        array (
          0 => 
          array (
            'name' => 'View Complete',
            'permission' => 'yes',
          ),
        ),
      ),
    )