如何在PHP数组中递归运行array_filter?

pep*_*epe 7 php recursion count array-filter

给出以下数组 $mm

Array
(
    [147] => Array
        (
            [pts_m] => 
            [pts_mreg] => 1
            [pts_cg] => 1
        )    
    [158] => Array
        (
            [pts_m] => 
            [pts_mreg] => 
            [pts_cg] => 0
        )

    [159] => Array
        (
            [pts_m] => 
            [pts_mreg] => 1
            [pts_cg] => 1
        )

)
Run Code Online (Sandbox Code Playgroud)

当我运行时,count(array_filter($mm))我得到3结果,因为它不是递归的.

count(array_filter($mm), COUNT_RECURSIVE)也不会这样做,因为我实际上需要array_filter递归运行,然后计算其结果.

所以我的问题是:array_filter($mm)在这种情况下如何递归运行?我的预期结果是4.

请注意,我没有使用任何回调,所以我可以排除false,null和empty.

Fra*_*nes 24

PHP array_filter文档:

//This function filters an array and remove all null values recursively. 

<?php 
  function array_filter_recursive($input) 
  { 
    foreach ($input as &$value) 
    { 
      if (is_array($value)) 
      { 
        $value = array_filter_recursive($value); 
      } 
    } 

    return array_filter($input); 
  } 
?> 

//Or with callback parameter (not tested) : 

<?php 
  function array_filter_recursive($input, $callback = null) 
  { 
    foreach ($input as &$value) 
    { 
      if (is_array($value)) 
      { 
        $value = array_filter_recursive($value, $callback); 
      } 
    } 

    return array_filter($input, $callback); 
  } 
?>
Run Code Online (Sandbox Code Playgroud)


Kin*_*nch 9

应该管用

$count = array_sum(array_map(function ($item) {
  return ((int) !is_null($item['pts_m'])
       + ((int) !is_null($item['pts_mreg'])
       + ((int) !is_null($item['pts_cg']);
}, $array);
Run Code Online (Sandbox Code Playgroud)

或者可能

$count = array_sum(array_map(function ($item) {
  return array_sum(array_map('is_int', $item));
}, $array);
Run Code Online (Sandbox Code Playgroud)

肯定有更多可能的解决方案.如果你想使用array_filter()(没有回调)记住,它把0false过,因此它会删除任何0从数组-值.

如果您在5.3之前的版本中使用PHP,我会使用foreach-loop

$count = 0;
foreach ($array as $item) {
  $count += ((int) !is_null($item['pts_m'])
          + ((int) !is_null($item['pts_mreg'])
          + ((int) !is_null($item['pts_cg']);
}
Run Code Online (Sandbox Code Playgroud)

更新

关于以下评论:

Thx @kc我实际上希望该方法删除false,0,empty等

当这真的只是你想要的时候,解决方案也很简单.但现在我不知道,如何解释

我的预期结果是5.

无论如何,它现在短:)

$result = array_map('array_filter', $array);
$count = array_map('count', $result);
$countSum = array_sum($count);
Run Code Online (Sandbox Code Playgroud)

结果数组看起来像

Array
(
[147] => Array
    (
        [pts_mreg] => 1
        [pts_cg] => 1
    )    
[158] => Array
    (
    )

[159] => Array
    (
        [pts_mreg] => 1
        [pts_cg] => 1
    )

)
Run Code Online (Sandbox Code Playgroud)


Eug*_*scu 5

一个更好的选择

总是对我有用的一个实现是这样的:

function filter_me(&$array) {
    foreach ( $array as $key => $item ) {
        is_array ( $item ) && $array [$key] = filter_me ( $item );
        if (empty ( $array [$key] ))
            unset ( $array [$key] );
    }
    return $array;
}
Run Code Online (Sandbox Code Playgroud)

我注意到有人创造了一个类似的功能,但在我看来,这个功能很少:

  1. 你传递一个数组作为参考(而不是它的副本),因此该算法是内存友好的
  2. 没有对array_filter的额外调用,实际上涉及:
    • 堆栈的使用,即.额外的记忆
    • 其他一些操作,即.CPU周期

基准

  1. 64MB阵列
    • filter_me函数在0.8s内完成,启动函数前PHP分配的内存为65MB,当函数返回时为39.35MB!
    • 上面由Francois Deschenes推荐的array_filter_recursive函数没有机会; 1s后PHP致命错误:允许的内存大小为134217728字节耗尽
  2. 36MB阵列
    • filter_me函数在0.4s内完成,启动函数前PHP分配的内存为36.8MB,当函数返回时为15MB!
    • array_filter_recursive函数这次以0.6s成功,而之前/之后的内存完全相同

我希望它有所帮助.