Recursively remove empty elements and subarrays from a multi-dimensional array

偶尔善良 提交于 2019-12-28 00:18:01

问题


I can't seem to find a simple, straight-forward solution to the age-old problem of removing empty elements from arrays in PHP.

My input array may look like this:

Array ( [0] => Array ( [Name] => [EmailAddress] => ) ) 

(And so on, if there's more data, although there may not be...)

If it looks like the above, I want it to be completely empty after I've processed it.

So print_r($array); would output:

Array ( )

If I run $arrayX = array_filter($arrayX); I still get the same print_r output. Everywhere I've looked suggests this is the simplest way of removing empty array elements in PHP5, however.

I also tried $arrayX = array_filter($arrayX,'empty_array'); but I got the following error:

Warning: array_filter() [function.array-filter]: The second argument, 'empty_array', should be a valid callback

What am I doing wrong?


回答1:


Try using array_map() to apply the filter to every array in $array:

$array = array_map('array_filter', $array);
$array = array_filter($array);

Demo: http://codepad.org/xfXEeApj




回答2:


There are numerous examples of how to do this. You can try the docs, for one (see the first comment).

function array_filter_recursive($array, $callback = null) {
    foreach ($array as $key => & $value) {
        if (is_array($value)) {
            $value = array_filter_recursive($value, $callback);
        }
        else {
            if ( ! is_null($callback)) {
                if ( ! $callback($value)) {
                    unset($array[$key]);
                }
            }
            else {
                if ( ! (bool) $value) {
                    unset($array[$key]);
                }
            }
        }
    }
    unset($value);

    return $array;
}

Granted this example doesn't actually use array_filter but you get the point.




回答3:


The accepted answer does not do exactly what the OP asked. If you want to recursively remove ALL values that evaluate to false including empty arrays then use the following function:

function array_trim($input) {
    return is_array($input) ? array_filter($input, 
        function (& $value) { return $value = array_trim($value); }
    ) : $input;
}

Or you could change the return condition according to your needs, for example:

{ return !is_array($value) or $value = array_trim($value); }

If you only want to remove empty arrays. Or you can change the condition to only test for "" or false or null, etc...




回答4:


Following up jeremyharris' suggestion, this is how I needed to change it to make it work:

function array_filter_recursive($array) {
   foreach ($array as $key => &$value) {
      if (empty($value)) {
         unset($array[$key]);
      }
      else {
         if (is_array($value)) {
            $value = array_filter_recursive($value);
            if (empty($value)) {
               unset($array[$key]);
            }
         }
      }
   }

   return $array;
}



回答5:


Try with:

$array = array_filter(array_map('array_filter', $array));

Example:

$array[0] = array(
   'Name'=>'',
   'EmailAddress'=>'',
);
print_r($array);

$array = array_filter(array_map('array_filter', $array));

print_r($array);

Output:

Array
(
    [0] => Array
        (
            [Name] => 
            [EmailAddress] => 
        )
)

Array
(
)



回答6:


array_filter() is not type-sensitive by default. This means that any zero-ish, false-y, null, empty values will be removed. My links to follow will demonstrate this point.

The OP's sample input array is 2-dimensional. If the data structure is static then recursion is not necessary. For anyone who would like to filter the zero-length values from a multi-dimensional array, I'll provide a static 2-dim method and a recursive method.

Static 2-dim Array: This code performs a "zero-safe" filter on the 2nd level elements and then removes empty subarrays: (See this demo to see this method work with different (trickier) array data)

$array=[
    ['Name'=>'','EmailAddress'=>'']
];   

var_export(
    array_filter(  // remove the 2nd level in the event that all subarray elements are removed
        array_map(  // access/iterate 2nd level values
            function($v){
                return array_filter($v,'strlen');  // filter out subarray elements with zero-length values
            },$array  // the input array
        )
    )
);

Here is the same code as a one-liner:

var_export(array_filter(array_map(function($v){return array_filter($v,'strlen');},$array)));

Output (as originally specified by the OP):

array (
)

*if you don't want to remove the empty subarrays, simply remove the outer array_filter() call.


Recursive method for multi-dimensional arrays of unknown depth: When the number of levels in an array are unknown, recursion is a logical technique. The following code will process each subarray, removing zero-length values and any empty subarrays as it goes. Here is a demo of this code with a few sample inputs.

$array=[
    ['Name'=>'','Array'=>['Keep'=>'Keep','Drop'=>['Drop2'=>'']],'EmailAddress'=>'','Pets'=>0,'Children'=>null],
    ['Name'=>'','EmailAddress'=>'','FavoriteNumber'=>'0']
];

function removeEmptyValuesAndSubarrays($array){
   foreach($array as $k=>&$v){
        if(is_array($v)){
            $v=removeEmptyValuesAndSubarrays($v);  // filter subarray and update array
            if(!sizeof($v)){ // check array count
                unset($array[$k]);
            }
        }elseif(!strlen($v)){  // this will handle (int) type values correctly
            unset($array[$k]);
        }
   }
   return $array;
}

var_export(removeEmptyValuesAndSubarrays($array));

Output:

array (
  0 => 
  array (
    'Array' => 
    array (
      'Keep' => 'Keep',
    ),
    'Pets' => 0,
  ),
  1 => 
  array (
    'FavoriteNumber' => '0',
  ),
)

If anyone discovers an input array that breaks my recursive method, please post it (in its simplest form) as a comment and I'll update my answer.



来源:https://stackoverflow.com/questions/9895130/recursively-remove-empty-elements-and-subarrays-from-a-multi-dimensional-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!