Рекурсивно удалять пустые элементы и подмассивы из многомерного массива

Я не могу найти простого, прямолинейного решения старой проблемы удаления пустых элементов из массивов в PHP.

Мой массив ввода может выглядеть следующим образом:

Array ( [0] => Array ( [Name] => [EmailAddress] => ) ) 

(И так далее, если есть больше данных, хотя их может не быть …)

Если он выглядит выше, я хочу, чтобы он был полностью пуст после того, как я его обработал.

Итак print_r($array); будет выводить:

 Array ( ) 

Если я запустил $arrayX = array_filter($arrayX); Я все равно получаю тот же вывод print_r . Повсюду, о котором я рассказывал, это самый простой способ удаления пустых элементов массива в PHP5.

Я также пробовал $arrayX = array_filter($arrayX,'empty_array'); но я получил следующую ошибку:

Предупреждение: array_filter () [function.array-filter]: Второй аргумент «empty_array» должен быть действительным обратным вызовом

Что я делаю не так?

Попробуйте использовать array_map() чтобы применить фильтр к каждому массиву в $array :

 $array = array_map('array_filter', $array); $array = array_filter($array); 

Демо: http://codepad.org/xfXEeApj

Существует множество примеров того, как это сделать. Вы можете попробовать документы , для одного (см. Первый комментарий).

 function array_filter_recursive($array, $callback = null) { foreach ($array as $key => & $value) { if (is_array($value)) { $value = array_filter_recursive($value, $callback); } else { if ( ! is_null($callback)) { if ( ! $callback($value)) { unset($array[$key]); } } else { if ( ! (bool) $value) { unset($array[$key]); } } } } unset($value); return $array; } с function array_filter_recursive($array, $callback = null) { foreach ($array as $key => & $value) { if (is_array($value)) { $value = array_filter_recursive($value, $callback); } else { if ( ! is_null($callback)) { if ( ! $callback($value)) { unset($array[$key]); } } else { if ( ! (bool) $value) { unset($array[$key]); } } } } unset($value); return $array; } с function array_filter_recursive($array, $callback = null) { foreach ($array as $key => & $value) { if (is_array($value)) { $value = array_filter_recursive($value, $callback); } else { if ( ! is_null($callback)) { if ( ! $callback($value)) { unset($array[$key]); } } else { if ( ! (bool) $value) { unset($array[$key]); } } } } unset($value); return $array; } с function array_filter_recursive($array, $callback = null) { foreach ($array as $key => & $value) { if (is_array($value)) { $value = array_filter_recursive($value, $callback); } else { if ( ! is_null($callback)) { if ( ! $callback($value)) { unset($array[$key]); } } else { if ( ! (bool) $value) { unset($array[$key]); } } } } unset($value); return $array; } 

Предоставленный этот пример фактически не использует array_filter но вы получаете точку.

Принятый ответ не делает точно то, что задает ОП. Если вы хотите рекурсивно удалить ВСЕ значения, которые вычисляют значение false, включая пустые массивы, используйте следующую функцию:

 function array_trim($input) { return is_array($input) ? array_filter($input, function (& $value) { return $value = array_trim($value); } ) : $input; } 

Или вы можете изменить условие возврата в соответствии с вашими потребностями, например:

 { return !is_array($value) or $value = array_trim($value); } 

Если вы хотите удалить пустые массивы. Или вы можете изменить условие, чтобы тестировать только «» или false или null, и т. Д. …

Следуя предложению jeremyharris, вот как мне нужно было изменить его, чтобы заставить его работать:

 function array_filter_recursive($array) { foreach ($array as $key => &$value) { if (empty($value)) { unset($array[$key]); } else { if (is_array($value)) { $value = array_filter_recursive($value); if (empty($value)) { unset($array[$key]); } } } } return $array; } с function array_filter_recursive($array) { foreach ($array as $key => &$value) { if (empty($value)) { unset($array[$key]); } else { if (is_array($value)) { $value = array_filter_recursive($value); if (empty($value)) { unset($array[$key]); } } } } return $array; } с function array_filter_recursive($array) { foreach ($array as $key => &$value) { if (empty($value)) { unset($array[$key]); } else { if (is_array($value)) { $value = array_filter_recursive($value); if (empty($value)) { unset($array[$key]); } } } } return $array; } 

Попробуйте:

 $array = array_filter(array_map('array_filter', $array)); 

Пример:

 $array[0] = array( 'Name'=>'', 'EmailAddress'=>'', ); print_r($array); $array = array_filter(array_map('array_filter', $array)); print_r($array); 

Вывод:

 Array ( [0] => Array ( [Name] => [EmailAddress] => ) ) Array ( ) 

array_filter() по умолчанию не чувствителен к типу. Это означает, что любые нулевые , ложные-y, null, пустые значения будут удалены. Мои ссылки, чтобы следовать, продемонстрируют этот момент.

Входной массив выборки OP является двумерным. Если структура данных статична, то рекурсия не требуется. Для тех, кто хочет отфильтровать значения нулевой длины из многомерного массива, я предоставил статический двухмерный метод и рекурсивный метод.

Static 2-dim Array : этот код выполняет «нулевой сейф» на элементах 2-го уровня, а затем удаляет пустые подмассивы: ( См. Эту демонстрацию, чтобы увидеть, как этот метод работает с разными (более сложными) массивами )

 $array=[ ['Name'=>'','EmailAddress'=>''] ]; var_export( array_filter( // remove the 2nd level in the event that all subarray elements are removed array_map( // access/iterate 2nd level values function($v){ return array_filter($v,'strlen'); // filter out subarray elements with zero-length values },$array // the input array ) ) ); 

Вот тот же код, что и однострочный:

 var_export(array_filter(array_map(function($v){return array_filter($v,'strlen');},$array))); 

Вывод (как первоначально указано OP):

 array ( ) 

* Если вы не хотите удалять пустые подмассивы, просто удалите внешний array_filter() .


Рекурсивный метод для многомерных массивов неизвестной глубины : когда количество уровней в массиве неизвестно, рекурсия является логическим методом. Следующий код будет обрабатывать каждый подмассив, удаляя значения нулевой длины и любые пустые подмассивы по мере их появления. Вот демонстрация этого кода с несколькими примерами ввода.

 $array=[ ['Name'=>'','Array'=>['Keep'=>'Keep','Drop'=>['Drop2'=>'']],'EmailAddress'=>'','Pets'=>0,'Children'=>null], ['Name'=>'','EmailAddress'=>'','FavoriteNumber'=>'0'] ]; function removeEmptyValuesAndSubarrays($array){ foreach($array as $k=>&$v){ if(is_array($v)){ $v=removeEmptyValuesAndSubarrays($v); // filter subarray and update array if(!sizeof($v)){ // check array count unset($array[$k]); } }elseif(!strlen($v)){ // this will handle (int) type values correctly unset($array[$k]); } } return $array; } var_export(removeEmptyValuesAndSubarrays($array)); с $array=[ ['Name'=>'','Array'=>['Keep'=>'Keep','Drop'=>['Drop2'=>'']],'EmailAddress'=>'','Pets'=>0,'Children'=>null], ['Name'=>'','EmailAddress'=>'','FavoriteNumber'=>'0'] ]; function removeEmptyValuesAndSubarrays($array){ foreach($array as $k=>&$v){ if(is_array($v)){ $v=removeEmptyValuesAndSubarrays($v); // filter subarray and update array if(!sizeof($v)){ // check array count unset($array[$k]); } }elseif(!strlen($v)){ // this will handle (int) type values correctly unset($array[$k]); } } return $array; } var_export(removeEmptyValuesAndSubarrays($array)); с $array=[ ['Name'=>'','Array'=>['Keep'=>'Keep','Drop'=>['Drop2'=>'']],'EmailAddress'=>'','Pets'=>0,'Children'=>null], ['Name'=>'','EmailAddress'=>'','FavoriteNumber'=>'0'] ]; function removeEmptyValuesAndSubarrays($array){ foreach($array as $k=>&$v){ if(is_array($v)){ $v=removeEmptyValuesAndSubarrays($v); // filter subarray and update array if(!sizeof($v)){ // check array count unset($array[$k]); } }elseif(!strlen($v)){ // this will handle (int) type values correctly unset($array[$k]); } } return $array; } var_export(removeEmptyValuesAndSubarrays($array)); 

Вывод:

 array ( 0 => array ( 'Array' => array ( 'Keep' => 'Keep', ), 'Pets' => 0, ), 1 => array ( 'FavoriteNumber' => '0', ), ) 

Если кто-либо обнаруживает входной массив, который разбивает мой рекурсивный метод, отправьте его (в его простейшей форме) в качестве комментария, и я обновлю свой ответ.