24

我似乎找不到一个简单、直接的解决方案来解决 PHP 中从数组中删除空元素的古老问题。

我的输入数组可能如下所示:

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

(等等,如果有更多的数据,虽然可能没有......)

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

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

Array ( )

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

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

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

我究竟做错了什么?

4

8 回答 8

46

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

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

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

于 2012-03-27T18:14:37.030 回答
6

有很多例子可以说明如何做到这一点。您可以尝试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;
}

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

于 2012-03-27T18:14:29.900 回答
5

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

于 2015-01-15T23:44:43.647 回答
4

遵循 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;
}
于 2014-01-23T21:02:53.447 回答
4

尝试:

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

例子:

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

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

print_r($array);

输出:

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

Array
(
)
于 2017-01-24T12:12:03.680 回答
3

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

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

静态 2-dim 数组:此代码对 2 级元素执行“零安全”过滤器,然后删除空子数组:(请参阅此演示以了解此方法适用于不同(更复杂的)数组数据

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

这是与单行代码相同的代码:

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

输出(最初由 OP 指定):

array (
)

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


未知深度的多维数组的递归方法:当数组中的层数未知时,递归是一种逻辑技术。以下代码将处理每个子数组,删除零长度值和任何空子数组。 这是此代码的演示,其中包含一些示例输入。

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

输出:

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

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

于 2017-10-17T02:30:42.170 回答
0

当被问到这个问题时,PHP 的最新版本是 5.3.10。到今天为止,它现在是 8.1.1,从那以后发生了很多变化!由于核心功能的变化,一些较早的答案将提供意想不到的结果。因此,我觉得需要一个最新的答案。下面将遍历一个数组,删除任何为空字符串、空数组或 null 的元素(因此 false 和 0 将保留),如果这导致更多的空数组,它也会删除它们。

function removeEmptyArrayElements( $value ) {
    if( is_array($value) ) {
        $value = array_map('removeEmptyArrayElements', $value);
        $value = array_filter( $value, function($v) {
            // Change the below to determine which values get removed
            return !( $v === "" || $v === null || (is_array($v) && empty($v)) );
        } );
    }
    return $value;
}

要使用它,您只需调用removeEmptyArrayElements( $array );

于 2022-02-08T00:10:09.980 回答
0

如果在类内部用作辅助方法:

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

    return $array;
}
于 2022-02-19T16:41:46.423 回答