如何在 PHP 数组中递归运行 array_filter?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6795621/
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
How to run array_filter recursively in a PHP array?
提问by pepe
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?
My expected result here would be 4
.
所以我的问题是:array_filter($mm)
在这种情况下我如何递归运行?我在这里的预期结果是4
.
Please note that I am not using any callback so I can exclude false, null and empty.
请注意,我没有使用任何回调,因此我可以排除 false、null 和 empty。
回答by Francois Deschenes
From the PHP array_filter
documentation:
//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);
}
?>
回答by KingCrunch
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 removeany 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']);
}
Update
更新
Regarding the comment below:
关于下面的评论:
Thx @kc I actually want the method to remove false, 0, empty etc
Thx @kc 我实际上希望该方法删除 false、0、empty 等
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
)
)
回答by Eugen Mihailescu
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:
我注意到有人创建了一个类似的函数,但在我看来,这个函数没有什么优势:
- you pass an array as reference (not its copy) and thus the algorithm is memory-friendly
- no additional calls to array_filter which in reality involves:
- the use of stack, ie. additional memory
- some other operations, ie. CPU cycles
- 你传递一个数组作为引用(而不是它的副本),因此该算法是内存友好的
- 没有对 array_filter 的额外调用,这实际上涉及:
- 堆栈的使用,即。额外的内存
- 其他一些操作,即。CPU周期
Benchmarks
基准
- A 64MB array
- filter_mefunction finished in 0.8s AND the PHP allocated memory before starting the function was 65MB, when function returned it was 39.35MB !!!
- array_filter_recursivefunction recommended above by Francois Deschenes had no chance; after 1s PHP Fatal error: Allowed memory size of 134217728 bytes exhausted
- A 36MB array
- filter_mefunction finished in 0.4s AND the PHP allocated memory before starting the function was 36.8MB, when function returned it was 15MB !!!
- array_filter_recursivefunction succeeded this time in 0.6s and memory before/after was quite the same
- 一个 64MB 的阵列
- filter_me函数在 0.8秒内完成,并且 PHP 在函数启动前分配的内存为 65MB,当函数返回时为 39.35MB !!!
- 上面 Francois Deschenes 推荐的array_filter_recursive函数没有机会;1 秒后 PHP 致命错误:允许的内存大小为 134217728 字节已用完
- 一个 36MB 的阵列
- filter_me函数在0.4 秒内完成,并且 PHP 在函数启动前分配的内存为 36.8MB,当函数返回时为 15MB !!!
- array_filter_recursive函数在 0.6秒内成功,前后内存完全相同
I hope it helps.
我希望它有帮助。
回答by helpse
This function effectively applies filter_recursive with a provided callback
此函数通过提供的回调有效地应用 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
这可能会帮助某人
回答by ling
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:
我需要一个数组过滤递归函数来遍历所有节点(包括数组,以便我们有可能丢弃整个数组),所以我想出了这个:
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
回答by Jrod
<?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;
?>