php 从多维数组中递归删除空元素和子数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9895130/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 07:52:09  来源:igfitidea点击:

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

phparraysmultidimensional-arrayfilteringis-empty

提问by Chuck Le Butt

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

我似乎无法找到一个简单、直接的解决方案来解决从 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 emptyafter I've processed it.

如果它看起来像上面那样,我希望它在处理后完全为空

So print_r($array);would output:

所以print_r($array);会输出:

Array ( )

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

如果我运行,$arrayX = array_filter($arrayX);我仍然会得到相同的print_r输出。然而,我看过的所有地方都表明这是在 PHP5 中删除空数组元素的最简单方法。

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

我也尝试过,$arrayX = array_filter($arrayX,'empty_array');但出现以下错误:

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

警告:array_filter() [function.array-filter]:第二个参数,'empty_array',应该是一个有效的回调

What am I doing wrong?

我究竟做错了什么?

回答by Wesley Murch

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

尝试使用array_map()将过滤器应用于 中的每个数组$array

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

Demo: http://codepad.org/xfXEeApj

演示:http: //codepad.org/xfXEeApj

回答by jeremyharris

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

有许多示例说明如何执行此操作。您可以尝试docs,一个(见第一条评论)。

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_filterbut you get the point.

当然,这个例子实际上并没有使用,array_filter但你明白了。

回答by Alain

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:

接受的答案并不完全符合 OP 的要求。如果要递归删除所有评估为 false 的值,包括空数组,请使用以下函数:

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...

如果您只想删除空数组。或者您可以将条件更改为仅测试 "" 或 false 或 null 等...

回答by joseantgv

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

回答by mickmackusa

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.

array_filter()默认情况下不区分类型。这意味着任何zero-ish、false-y、null、空值都将被删除。我要遵循的链接将证明这一点。

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.

OP 的样本输入数组是二维的。如果数据结构是静态的,则不需要递归。对于想要从多维数组中过滤零长度值的任何人,我将提供静态二维方法和递归方法。

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

输出(最初由 OP 指定):

array (
)

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

*如果您不想删除空子数组,只需删除外部array_filter()调用即可。



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.

如果有人发现破坏了我的递归方法的输入数组,请将其发布(以最简单的形式)作为评论,我将更新我的答案。

回答by CodedMonkey

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

遵循 jeremyharris 的建议,这就是我需要对其进行更改以使其正常工作的方式:

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;
}