Как запустить фильтр массива рекурсивно в массиве PHP?
учитывая следующий массив $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 и пустой.
5 ответов
должно работать
$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
as false
и поэтому удалить любой 0
-значение из массива.
если вы используете PHP в версии pre-5.3, я бы использовал 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 etc
когда это действительно только то, что вы хотите, решение тоже очень простое. Но теперь я не знаю, как истолковать
мой ожидаемый результат здесь будет 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
)
)
С 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);
}
?>
лучшая альтернатива
одна реализация, которая всегда работала для меня, это:
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;
}
Я замечаю, что кто-то создал аналогичную функцию, за исключением того, что эта представляет, на мой взгляд, несколько преимуществ:
- вы передаете массив в качестве ссылки (а не его копию), и, таким образом, алгоритм удобен для памяти
- никаких дополнительных вызовов array_filter, который на самом деле включает:
- использование стека, то есть. дополнительная память
- некоторые другие операции, т. е.. CPU cycles
критерии
- размером 64Мб массива
- filter_me функция закончена в 0.8 s и выделенная PHP память перед запуском функции была 65MB, когда функция вернулась, это было 39.35 MB !!!
- array_filter_recursive
эта функция эффективно применяет 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);
Это может помочь кому-то
<?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;
?>