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

Я не могу найти простое, прямое решение вековой проблемы удаления пустых элементов из массивов в 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);

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


существует множество примеров того, как это сделать. Вы можете попробовать 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',
  ),
)

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