php 计算二维数组中的“真实”值

68de4m5k  于 2022-12-02  发布在  PHP
关注(0)|答案(8)|浏览(147)

给定以下数组$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
        )

)

当我运行count(array_filter($mm))时,我得到3作为结果,因为它不是递归的。
count(array_filter($mm), COUNT_RECURSIVE)也不行,因为我实际上需要递归地运行array_filter,然后计算其结果。
所以我的问题是:在这种情况下,我如何递归地运行array_filter($mm)?我期望的结果是4
请注意,我没有使用任何回调函数,因此可以排除false、null和empty。

eeq64g8w

eeq64g8w1#

来自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); 
  } 
?>
3z6pesqy

3z6pesqy2#

应该可以

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

或者也许

$count = array_sum(array_map(function ($item) {
  return array_sum(array_map('is_int', $item));
}, $array);

如果你想使用array_filter()(没有回调函数),记住,它也会把0当作false,因此它会从数组中 * 移除 * 任何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']);
}

更新

关于以下意见:
Thx @kc我实际上希望该方法删除false,0,empty等
当这真的只是,你想要的,解决的办法也很简单。但现在我不知道,如何解释
我的预期结果是5。
不管怎么说,它现在很短:)

$result = array_map('array_filter', $array);
$count = array_map('count', $result);
$countSum = array_sum($count);

生成的数组如下所示

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

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

)
z9smfwbn

z9smfwbn3#

更好的选择

一个一直对我有效的实现是这样的:

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

我注意到有人创建了一个类似的函数,但在我看来,这个函数没有什么优点:
1.您将数组作为引用(而不是其副本)传递,因此该算法是内存友好的

  • 没有对array_filter的额外调用,实际上涉及:
  • 堆栈使用,即附加存储器
  • 一些其他操作,即CPU周期
    性能指标评测
  • 64 MB阵列
  • filter_me 函数在0.8秒内完成,并且PHP在启动函数之前分配的内存为65 MB,函数返回时分配的内存为39.35MB!!!
  • 上面Francois Deschenes推荐的 array_filter_recursive 函数没有机会; PHP致命错误:已用完允许的内存大小134217728字节
  • 36 MB阵列
  • filter_me 函数在0.4秒内完成,并且PHP在启动函数之前分配的内存为36.8MB,函数返回时分配的内存为15 MB!!!
  • array_filter_recursive 函数这次在0.6秒内成功,并且之前/之后的内存完全相同

希望能帮上忙。

alen0pnh

alen0pnh4#

此函数通过提供的回调有效地应用filter_recursive

class Arr {

    public static function filter_recursive($array, $callback = NULL)
    {
        foreach ($array as $index => $value)
        {
            if (is_array($value))
            {
                $array[$index] = Arr::filter_recursive($value, $callback);
            }
            else
            {
                $array[$index] = call_user_func($callback, $value);
            }

            if ( ! $array[$index])
            {
                unset($array[$index]);
            }
        }

        return $array;
    }

}

你可以这样使用它:

Arr::filter_recursive($my_array, $my_callback);

这也许能帮到某人

cigdeys3

cigdeys35#

我需要一个遍历所有节点(包括数组)的数组过滤器递归函数,因此我提出了以下方法:

public static function filterRecursive(array $array, callable $callback): array
    {
        foreach ($array as $k => $v) {
            $res = call_user_func($callback, $v);
            if (false === $res) {
                unset($array[$k]);
            } else {
                if (is_array($v)) {
                    $array[$k] = self::filterRecursive($v, $callback);
                }
            }
        }

        return $array;
    }

请在此处查看更多示例:https://github.com/lingtalfi/Bat/blob/master/ArrayTool.md#filterrecursive

unftdfkk

unftdfkk6#

这应该适用于回调和模式支持沿着可选的深度支持。

function array_filter_recursive(array $array, callable $callback = null, int $mode = 0, int $depth = -1): array
{
    foreach ($array as & $value) {
        if ($depth != 0 && is_array($value)) {
            $value = array_filter_recursive($value, $callback, $mode, $depth - 1);
        }
    }

    if ($callback) {
        return array_filter($array, $callback, $mode);
    }

    return array_filter($array);
}

对于嵌套数组,使用$depth = 0调用函数将产生与array_filter相同的结果。

4zcjmb1e

4zcjmb1e7#

这让我觉得是一个XY Problem
1.递归不是必需的,因为数组具有一致的2级深度。
1.不需要生成一个筛选元素数组,这样您就可以遍历筛选数据来对其进行计数。只需遍历一次,并在遇到真实值时将count变量加1即可。
下面的代码段不调用函数(只调用语言构造--foreach()),因此效率很高。
代码:(Demo

$truthyCount = 0;
foreach ($array as $row) {
    foreach ($row as $v) {
        $truthyCount += (bool) $v;
    }
}
var_export($truthyCount);
jgzswidk

jgzswidk8#

<?php

$mm = array
(
    147 => array
        (
            "pts_m" => "",
            "pts_mreg" => 1,
            "pts_cg" => 1
        ) ,
    158 => array
        (
            "pts_m" => null ,
            "pts_mreg" => null,
            "pts_cg" => 0
        ),

    159 => array
        (
            "pts_m" => "",
            "pts_mreg" => 1,
            "pts_cg" => 1
        )

);

$count = 0;
foreach ($mm as $m) {
    foreach ($m as $value) {
        if($value !== false && $value !== "" && $value !== null) {
            $count++;
        }
    }
}
echo $count;
?>

相关问题