[英]Count "truthy" values in a 2d array
Given the following array $mm
给定以下数组
$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
)
)
When I run count(array_filter($mm))
I get 3
as result since it is not recursive.当我运行
count(array_filter($mm))
时,我得到3
作为结果,因为它不是递归的。
count(array_filter($mm), COUNT_RECURSIVE)
also will not do because I actually need to run the array_filter
recursively, and then count its result. count(array_filter($mm), COUNT_RECURSIVE)
也不会这样做,因为我实际上需要递归地运行array_filter
,然后计算它的结果。
So my question is: how do I recursively run array_filter($mm)
in this case?所以我的问题是:在这种情况下如何递归运行
array_filter($mm)
? My expected result here would be 4
.我在这里的预期结果是
4
。
Please note that I am not using any callback so I can exclude false, null and empty.请注意,我没有使用任何回调,因此我可以排除错误、null 和空。
From the PHP array_filter
documentation :来自
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);
}
?>
Should work应该管用
$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);
or maybe或者可能
$count = array_sum(array_map(function ($item) {
return array_sum(array_map('is_int', $item));
}, $array);
There are definitely many more possible solutions.肯定有更多可能的解决方案。 If you want to use
array_filter()
(without callback) remember, that it treats 0
as false
too and therefore it will remove any 0
-value from the array.如果你想使用
array_filter()
(没有回调)请记住,它也将0
视为false
,因此它将从数组中删除任何0
值。
If you are using PHP in a pre-5.3 version, I would use a foreach
-loop如果您在 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']);
}
Regarding the comment below:关于下面的评论:
Thx @kc I actually want the method to remove false, 0, empty etc
Thx @kc 我实际上希望该方法删除 false、0、空等
When this is really only, what you want, the solution is very simple too.当这真的只是你想要的,解决方案也很简单。 But now I don't know, how to interpret
但是现在不知道怎么解释
My expected result here would be 5.
我的预期结果是 5。
Anyway, its short now:)无论如何,它现在很短:)
$result = array_map('array_filter', $array);
$count = array_map('count', $result);
$countSum = array_sum($count);
The resulting array looks like结果数组看起来像
Array
(
[147] => Array
(
[pts_mreg] => 1
[pts_cg] => 1
)
[158] => Array
(
)
[159] => Array
(
[pts_mreg] => 1
[pts_cg] => 1
)
)
A better alternative更好的选择
One implementation that always worked for me is this one:一种一直对我有用的实现是这个:
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;
}
I notice that someone had created a similar function except that this one presents, in my opinion, few advantages:我注意到有人创建了一个类似的 function,但在我看来,这个有几个优点:
Benchmarks基准
I hope it helps.我希望它有所帮助。
This function effectively applies filter_recursive with a provided callback这个 function 通过提供的回调有效地应用 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;
}
}
And you'd use it this way:你会这样使用它:
Arr::filter_recursive($my_array, $my_callback);
This might help someone这可能会帮助某人
I needed an array filter recursive function that would walk through all nodes (including arrays, so that we have the possibility to discard entire arrays), and so I came up with this:我需要一个数组过滤器递归 function 将遍历所有节点(包括 arrays,以便我们有可能丢弃整个数组),所以我想出了这个:
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;
}
See more examples here: https://github.com/lingtalfi/Bat/blob/master/ArrayTool.md#filterrecursive在此处查看更多示例: https://github.com/lingtalfi/Bat/blob/master/ArrayTool.md#filterrecursive
This should work for callback and mode support along with an optional support for depth.这应该适用于回调和模式支持以及对深度的可选支持。
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);
}
Calling the function with $depth = 0
for nested arrays, will yield the same result as array_filter
.为嵌套的 arrays 调用
$depth = 0
的array_filter
,将产生与 array_filter 相同的结果。
This strike me as an XY Problem .这让我觉得是一个XY 问题。
The following snippet calls no functions (only language constructs -- foreach()
) and therefore will be highly efficient.以下代码段不调用任何函数(仅调用语言构造 --
foreach()
),因此效率很高。
$truthyCount = 0;
foreach ($array as $row) {
foreach ($row as $v) {
$truthyCount += (bool) $v;
}
}
var_export($truthyCount);
<?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;
?>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.