Как рекурсивно запустить array_filter в массиве 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 и empty.

Должно сработать

 $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.

Если вы используете PHP в версии до 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, пусто и т. Д.

Когда это действительно так, то, что вы хотите, решение очень просто. Но теперь я не знаю, как интерпретировать

Мой ожидаемый результат здесь будет 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; } 

Я замечаю, что кто-то создал подобную функцию, за исключением того, что это, на мой взгляд, представляет несколько преимуществ:

  1. вы передаете массив как ссылку (а не его копию), и, таким образом, алгоритм совместим с памятью
  2. никаких дополнительных вызовов для array_filter, которые в действительности связаны с:
    • использование стека, т.е. дополнительная память
    • некоторые другие операции, т.е. Циклы процессора

Ориентиры

  1. Массив 64 МБ
    • Функция filter_me завершена в 0.8 с И выделенная память PHP перед запуском функции была 65 МБ, когда функция вернулась, она была 39.35 МБ !!!
    • Функция array_filter_recursive, рекомендованная ранее Франсуа Дешенесом, не имела никаких шансов; после 1s PHP Неустранимая ошибка: разрешенный размер памяти 134217728 байт исчерпан
  2. Массив 36 МБ
    • Функция filter_me закончена в 0,4 с. И выделенная память PHP до запуска функции была 36,8 МБ, когда функция вернулась, она была 15 МБ !!!
    • Функция array_filter_recursive на этот раз преуспела в 0,6 секунды, а память до / после была совершенно одинаковой

Я надеюсь, что это помогает.

Эта функция эффективно применяет 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; } } с 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; ?>