Рекурсивное удаление пустых элементов и подрешеток из многомерного массива
Я не могу найти простое, прямое решение вековой проблемы удаления пустых элементов из массивов в PHP.
мой входной массив может выглядеть так:
Array ( [0] => Array ( [Name] => [EmailAddress] => ) )
(и так далее, если есть больше данных, хотя там может и не быть...)
если это выглядит как выше, я хочу, чтобы это было совершенно пустой после того, как я обработал его.
так print_r($array);
выводит:
Array ( )
если я запускаю $arrayX = array_filter($arrayX);
I все равно получишь то же самое print_r
выход. Однако везде, где я смотрел, это самый простой способ удаления пустых элементов массива в PHP5.
Я тоже пробовал $arrayX = array_filter($arrayX,'empty_array');
но я получил следующую ошибку:
предупреждение: array_filter() [функция.array-filter]: второй аргумент, 'empty_array', должен быть допустимым обратным вызовом
что я делаю не так?
6 ответов
попробуйте использовать array_map()
применить фильтр к каждому массиву в $array
:
$array = array_map('array_filter', $array);
$array = array_filter($array);
существует множество примеров того, как это сделать. Вы можете попробовать docs, например (см. Первый комментарий).
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;
}
попробовать с:
$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()
по умолчанию не чувствителен к типу. Это означает, что любой ноль-иш, false-y, null, пустые значения будут удалены. Мои ссылки, чтобы следовать, продемонстрируют этот момент.
входной массив выборки OP является 2-мерным. Если структура данных статична, рекурсия не требуется. Для тех, кто хотел бы отфильтровать значения нулевой длины из многомерного массива, я предоставлю статический 2-dim метод и рекурсивный метод.
статический 2-тусклый массив: Этот код выполняет" нулевой безопасный " фильтр на элементах 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 (
0 =>
array (
'Array' =>
array (
'Keep' => 'Keep',
),
'Pets' => 0,
),
1 =>
array (
'FavoriteNumber' => '0',
),
)
если кто-нибудь обнаруживает входной массив это нарушает мой рекурсивный метод, пожалуйста, опубликуйте его (в его простейшей форме) в качестве комментария, и я обновлю свой ответ.