2012-03-27 14 views
15

Parece que no puedo encontrar una solución sencilla y directa al antiguo problema de eliminar elementos vacíos de las matrices en PHP.Eliminación recursiva de elementos vacíos y subcampos de una matriz multidimensional

Mi matriz de entrada puede tener este aspecto:

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

(Y así sucesivamente, si hay más datos, aunque puede que no haya ...)

Si se parece a lo anterior, quiero que sea completamente vacío después de haberlo procesado.

Así print_r($array); habría de salida:

Array () 

Si me quedo $arrayX = array_filter($arrayX); sigo teniendo el mismo print_r salida. Sin embargo, en todas partes que he buscado, esta es la forma más simple de eliminar elementos de matriz vacíos en PHP5.

También probé $arrayX = array_filter($arrayX,'empty_array'); pero me dio el siguiente error:

Warning: array_filter() [function.array-filter]: The second argument, 'empty_array', should be a valid callback

¿Qué estoy haciendo mal?

+0

array_filter está configurado para matrices 1D. –

+0

¿Puede dar ejemplos de entrada, con salida esperada, por favor? Hay algunas maneras diferentes de interpretar su pregunta, * "Si se ve como lo de arriba, quiero que esté completamente vacío después de que lo haya procesado". * Me está tirando, ¿quiere que desaparezca por completo o ser una matriz vacía? –

+0

Esta es una matriz multidimensional. array_filter solo funciona en una dimensión. Necesita iterar a través de su matriz y aplicar array_filter a cada iteración primero. – Nilpo

Respuesta

21

Trate de usar array_map() para aplicar el filtro a cada matriz en $array:

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

Demostración: http://codepad.org/xfXEeApj

+1

Espera, ¿deseaba eliminar la matriz completa solo si * todos los elementos están vacíos? ? Eso no es lo que hace esto. ¿Puede dar ejemplos de entrada, con salida esperada, por favor? –

+1

No. Esto no funciona: -/ –

+0

Según su pregunta y la aclaración en los comentarios, sí debería: http://codepad.org/FdfY5aqj Cuando se eliminan todos los elementos vacíos, termina con una matriz vacía. Si esto no es lo que desea, por favor ingrese una muestra de entrada con el resultado esperado. ¿Le preocupa el efecto secundario de eliminar vacíos de las otras matrices? –

7

Existen numerosos ejemplos de cómo hacer esto. Puede probar el docs, para uno (vea el primer comentario).

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; 
} 

Concedido este ejemplo en realidad no utilizar array_filter pero usted consigue el punto.

+0

Este código no pudo desarmar la matriz más profunda de 0 de longitud, y no pudo seguir y borrar la estructura de triple anidación que estaba en – CodedMonkey

3

Siguiendo la sugerencia jeremyharris', esta es la forma en que tenía que cambiar para que funcione:

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; 
} 
4

La respuesta aceptada no hace exactamente lo que el OP solicitó. Si desea eliminar de forma recursiva TODOS los valores que se evalúan como falsas incluyendo matrices vacías a continuación, utilizar la siguiente función:

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

O puede cambiar la condición de retorno de acuerdo a sus necesidades, por ejemplo:

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

Si solo quiere eliminar matrices vacías. O puede cambiar la condición para que solo pruebe "" o sea falso o nulo, etc.

2

Try con:

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

Ejemplo:

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

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

print_r($array); 

de salida:

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

Array 
(
) 
0

array_filter() no es de tipo sensible de forma predeterminada. Esto significa que cualquier zero-ish, false-y, nulo, los valores vacíos serán eliminados. Mis enlaces a seguir demostrarán este punto.

La matriz de entrada de muestra del OP es bidimensional. Si la estructura de datos es estática, la recursión no es necesaria. Para cualquiera que quiera filtrar los valores de longitud cero de una matriz multidimensional, proporcionaré un método estático de 2 dim y un método recursivo.

estático 2-dim matriz de: Este código realiza un filtro de "cero-safe" en los elementos 2º nivel y luego elimina subarrays vacíos: (See this demo to see this method work with different (trickier) array data)

$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 
     ) 
    ) 
); 

aquí es el mismo código como una sola línea:

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

de salida (como se especifica originalmente por el OP):

array (
) 

* si no desea eliminar los subpaneles vacíos, simplemente elimine la llamada externa array_filter().


método recursivo para matrices multi-dimensionales de profundidad desconocida: Cuando se desconoce el número de niveles en una matriz, la recursión es una técnica de lógica. El siguiente código procesará cada subcampo, eliminando los valores de longitud cero y cualquier subarreglo vacío a medida que avanza. Here is a demo of this code with a few sample inputs.

$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)); 

Salida:

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

Si alguien descubre una matriz de entrada que rompe mi método recursivo, por favor, puesto que (en su forma más simple) como un comentario y voy a actualizar mi respuesta.

Cuestiones relacionadas