Eliminar elementos de matriz vacíos

784

Algunos elementos en mi matriz son cadenas vacías basadas en lo que el usuario ha enviado. Necesito eliminar esos elementos. Tengo esto:

foreach($linksArray as $link)
{
    if($link == '')
    {
        unset($link);
    }
}
print_r($linksArray);

Pero no funciona. $linksArrayTodavía tiene elementos vacíos. También intenté hacerlo con la empty()función, pero el resultado es el mismo.

Será
fuente
1
Pensé que valía la pena mencionar que el código anterior no funciona porque unset (...) opera en la variable creada por el bucle foreach, no en la matriz original que obviamente permanece como estaba antes del bucle.
savedario
if (! empty ($ link)) {echo $ link; } esto funciona para mí
Shiplu
¡Estás cambiando un enlace $ que no está referenciado! use foreach ($ linksArray como $ key => $ link) unset (linksArray [$ key])
TD_Nijboer

Respuestas:

1548

Como se trata de una serie de cadenas, simplemente puede usar array_filter(), que maneja convenientemente todo esto por usted:

print_r(array_filter($linksArray));

Tenga en cuenta que si no se proporciona una devolución de llamada , se eliminarán todas las entradas de la matriz igual a FALSE(consulte la conversión a booleana ). Entonces, si necesita preservar elementos que son, por ejemplo, una cadena exacta '0', necesitará una devolución de llamada personalizada:

// PHP 7.4 and later
print_r(array_filter($linksArray, fn($value) => !is_null($value) && $value !== ''));

// PHP 5.3 and later
print_r(array_filter($linksArray, function($value) { return !is_null($value) && $value !== ''; }));

// PHP < 5.3
print_r(array_filter($linksArray, create_function('$value', 'return $value !== "";')));
BoltClock
fuente
16
array_filterDebe eliminar los elementos vacíos. Y si la definición de vacío de PHP no es la misma que su definición, entonces puede completar la opción de devolución de llamada con una función anónima que arroja elementos no deseados. Aparentemente debe tener php 5.3 o posterior para usar devoluciones de llamadas anónimas. stackoverflow.com/questions/2412299/…
Buttle Butkus
76
cuidado con array_filter no reindexa los índices de la matriz (puede ocurrir un problema al usar la matriz de procesos en la declaración). Así que envuélvelo todo con la función array_values.
Michal - wereda-net
8
La respuesta es incorrecta, porque también eliminará falseelementos. ( php.net/manual/en/function.array-filter.php )
pliashkou
55
@Deji, ¿has intentado imprimir esa matriz antes de filtrarla? Creo que configurar ala segunda vez simplemente restablece la primera.
Cullub
55
@Cranio: que ya está cubierto por otro comentario. No es incorrecto, pero quizás más amplio que sus requisitos. Eso no significa que otras personas aún no puedan encontrarlo útil; después de todo, si todo lo que tiene son cadenas en su matriz, esta respuesta eliminará solo las vacías.
Martijn Pieters
169

Puede usar array_filterpara eliminar elementos vacíos:

$emptyRemoved = array_filter($linksArray);

Si tiene (int) 0en su matriz, puede usar lo siguiente:

$emptyRemoved = remove_empty($linksArray);

function remove_empty($array) {
  return array_filter($array, '_remove_empty_internal');
}

function _remove_empty_internal($value) {
  return !empty($value) || $value === 0;
}

EDITAR: Tal vez sus elementos no están vacíos per se pero contienen uno o más espacios ... Puede usar lo siguiente antes de usararray_filter

$trimmedArray = array_map('trim', $linksArray);
Andrew Moore
fuente
10
Acabo de agregarlo a la respuesta aceptada por BoltClock, simplemente puede hacer array_filter ($ foo, 'strlen') para evitar el problema "0" y solo eliminar aquellos con longitud cero.
AB Carroll
2
@nezZario: Suponiendo que solo tiene scalarelementos en su matriz, sí. De lo contrario, no puedes hacer eso.
Andrew Moore
2
Usando lambda para php> = 5.3function remove_empty($array) { return array_filter($array, function($value){return !empty($value) || $value === 0;}); }
Viral
1
array_map()hizo la magia porque tenía espacios en esas matrices vacías!
Prodigy
127

La respuesta más popular sobre este tema es absolutamente INCORRECTA.

Considere el siguiente script PHP:

<?php
$arr = array('1', '', '2', '3', '0');
// Incorrect:
print_r(array_filter($arr));
// Correct:
print_r(array_filter($arr, 'strlen'));

¿Por qué es esto? Debido a que una cadena que contiene un solo carácter '0' también se evalúa como falso booleano, por lo que, aunque no es una cadena vacía, aún se filtrará. Eso sería un error.

Pasar la función strlen incorporada como la función de filtrado funcionará, ya que devuelve un entero distinto de cero para una cadena no vacía y un entero cero para una cadena vacía. Los enteros distintos de cero siempre se evalúan como verdaderos cuando se convierten en booleanos, mientras que los enteros cero siempre se evalúan como falsos cuando se convierten en booleanos.

Entonces, la respuesta absoluta, definitiva y correcta es:

$arr = array_filter($arr, 'strlen');
Ron Cemer
fuente
3
Convenido. Esta debería ser la respuesta aceptada, para aquellos cuya matriz contiene cadenas
mwieczorek
2
Votado Una respuesta mejor que muchas de las otras, sin embargo, debe tenerse en cuenta que la respuesta actualmente aceptada no es técnicamente incorrecta ya que "vacío" tiene un significado especial dentro de PHP. (Algunos valores que califican como "vacío": 0, "", null)
rinogo
55
No son incorrectos, se trata de contexto. En algunos casos, preservar el valor 0 podría ser importante. Así que por favor, no digas que todos están equivocados excepto tú
Macr1408
66
Esto se rompe si la matriz contiene otra matriz:strlen() expects parameter 1 to be string, array given
hpaknia
Puede decir que esto también puede ser un buen enfoque (en lugar de decir que otros son incorrectos) para lograr las acciones deseadas. Básicamente, no todos los casos son similares. Aunque este enfoque está funcionando para mi caso.
MR_AMDEV
102
$linksArray = array_filter($linksArray);

"Si no se proporciona devolución de llamada, se eliminarán todas las entradas de entrada iguales a FALSO". - http://php.net/manual/en/function.array-filter.php

tamasd
fuente
44
También probé esto después de que Google solucionó el problema. Desafortunadamente, me deja en blanco los elementos.
Will
18
esto también eliminará '0'
OIS
2
@ Will: ¿estás seguro? También elimina cadenas vacías, probé con éxito esto. Tal vez sus valores de entrada contienen espacios y deberían recortarse antes. De acuerdo con las reglas de conversión booleana, la cadena vacía se evalúa como falsa y, por lo tanto, se elimina mediante array_filter.
acme
52
    $myarray = array_filter($myarray, 'strlen');  //removes null values but leaves "0"
    $myarray = array_filter($myarray);            //removes all null values
matija kancijan
fuente
strlen también elimina false :(
justnorris
42

Solo puedes hacer

array_filter($array)

array_filter: "Si no se proporciona devolución de llamada, se eliminarán todas las entradas de entrada iguales a FALSE". Esto significa que los elementos con valores NULL, 0, '0', '', FALSE, array () también se eliminarán.

La otra opción es hacer

array_diff($array, array(''))

que eliminará elementos con valores NULL '' y FALSE.

Espero que esto ayude :)

ACTUALIZAR

Aquí hay un ejemplo.

$a = array(0, '0', NULL, FALSE, '', array());

var_dump(array_filter($a));
// array()

var_dump(array_diff($a, array(0))) // 0 / '0'
// array(NULL, FALSE, '', array());

var_dump(array_diff($a, array(NULL))) // NULL / FALSE / ''
// array(0, '0', array())

Para resumir:

  • 0 o '0' eliminarán 0 y '0'
  • NULL, FALSE o '' eliminarán NULL, FALSE y ''
ayuda
fuente
36
foreach($linksArray as $key => $link) 
{ 
    if($link === '') 
    { 
        unset($linksArray[$key]); 
    } 
} 
print_r($linksArray); 
Mark Baker
fuente
44
Una solución concisa, legible y segura que no elimina falsey 0. Teniendo en cuenta que esto se publicó en el mismo minuto que la respuesta aceptada (que es insegura e incorrecta), solo puedo suponer que sus 8 votos positivos en comparación con los 649 de la respuesta aceptada se deben a que esta última es una solución de una línea.
rybo111
@ rybo111 - posiblemente, aunque usar esa lógica en una devolución de llamada array_filter()sería un enfoque más limpio que un foreach()bucle
Mark Baker
Quizás más rápido, pero su solución es la más fácil de leer, lo cual es importante. Para aquellos que usan su solución trim(), les recomendaríaif(is_string($link) && trim($link) === '')
rybo111
33

Otro forro para eliminar elementos vacíos ("" cadenas vacías) de su matriz.

$array = array_filter($array, function($a) {return $a !== "";});

Nota: Este código se mantiene deliberadamente null, 0y falseelementos.


O tal vez desee recortar los elementos de su matriz primero:

$array = array_filter($array, function($a) {
    return trim($a) !== "";
});

Nota: Este código también elimina elementos nully falseelementos.

marcovtwout
fuente
3
Exactamente lo que necesitaba, y esto también es compatible con PHP anteriores , ¡gracias! ;-)
Stano
1
@JohnK Incorrecto. Para hacer esto exactamente como el usuario quiere la devolución de llamada es necesario, a menos que desee eliminar los ceros alzo y otros valores falsey.
Cranio
Oh ... esto es absolutamente encantador. Debería ser el aceptado.
Henrik Petterson el
20

En breve:

Este es mi código sugerido:

$myarray =  array_values(array_filter(array_map('trim', $myarray), 'strlen'));

Explicación:

Creo que el uso array_filteres bueno, pero no suficiente, porque los valores son como spacey \n... se mantienen en la matriz y esto generalmente es malo.

Así que le sugiero que utilice mezcla array_filtery array_map.

array_mapes para recortar, array_filteres para eliminar valores vacíos, strlenes para mantener el 0valor y array_valueses para volver a indexar si es necesario.

Muestras:

$myarray = array("\r", "\n", "\r\n", "", " ", "0", "a");

// "\r", "\n", "\r\n", " ", "a"
$new1 = array_filter($myarray);

// "a"
$new2 = array_filter(array_map('trim', $myarray));

// "0", "a"
$new3 = array_filter(array_map('trim', $myarray), 'strlen');

// "0", "a" (reindex)
$new4 = array_values(array_filter(array_map('trim', $myarray), 'strlen'));

var_dump($new1, $new2, $new3, $new4);

Resultados:

array(5) {
  [0]=>
" string(1) "
  [1]=>
  string(1) "
"
  [2]=>
  string(2) "
"
  [4]=>
  string(1) " "
  [6]=>
  string(1) "a"
}
array(1) {
  [6]=>
  string(1) "a"
}
array(2) {
  [5]=>
  string(1) "0"
  [6]=>
  string(1) "a"
}
array(2) {
  [0]=>
  string(1) "0"
  [1]=>
  string(1) "a"
}

Prueba en línea:

http://phpio.net/s/5yg0

Nabi KAZ
fuente
13

Si está trabajando con una matriz numérica y necesita volver a indexar la matriz después de eliminar elementos vacíos, use la función array_values :

array_values(array_filter($array));

Ver también: PHP reindex array?

mulquin
fuente
12

La respuesta más votada es incorrecta o al menos no completamente cierta, ya que el OP solo habla de cadenas en blanco. Aquí hay una explicación detallada:

¿Qué significa vacío ?

En primer lugar, debemos acordar lo que significa vacío . ¿Te refieres a filtrar:

  1. las cadenas vacías solamente ( "")?
  2. los valores estrictamente falsos ? ( $element === false)
  3. los valores falsey ? (es decir, 0, 0.0, "", "0", NULL, array () ...)
  4. ¿El equivalente de la empty()función de PHP ?

¿Cómo se filtran los valores?

Para filtrar solo cadenas vacías :

$filtered = array_diff($originalArray, array(""));

Para filtrar solo valores estrictamente falsos , debe usar una función de devolución de llamada :

$filtered = array_diff($originalArray, 'myCallback');
function myCallback($var) {
    return $var === false;
}

La devolución de llamada también es útil para cualquier combinación en la que desee filtrar los valores "falsey", excepto algunos. (Por ejemplo, filtre cada nully false, etc., dejando solo 0):

$filtered = array_filter($originalArray, 'myCallback');
function myCallback($var) {
    return ($var === 0 || $var === '0');
}

El tercer y cuarto caso son (para nuestros fines, por fin) equivalentes, y para eso todo lo que tiene que usar es el predeterminado:

$filtered = array_filter($originalArray);
Cráneo
fuente
2
Si desea eliminar nully falsedejar 0, también puede utilizar la función incorporada de php strlencomo devolución de llamada.
Cullub
10

Tuve que hacer esto para mantener un valor de matriz de (cadena) 0

$url = array_filter($data, function ($value) {
  return (!empty($value) || $value === 0 || $value==='0');
});
Mate
fuente
9
$a = array(1, '', '', '', 2, '', 3, 4);
$b = array_values(array_filter($a));

print_r($b)
usuario2511140
fuente
9

Para matriz multidimensional

$data = array_map('array_filter', $data);
$data = array_filter($data);
HMagdy
fuente
9
$out_array = array_filter($input_array, function($item) 
{ 
    return !empty($item['key_of_array_to_check_whether_it_is_empty']); 
}
);
Naitik Shah
fuente
9
function trim_array($Array)
{
    foreach ($Array as $value) {
        if(trim($value) === '') {
            $index = array_search($value, $Array);
            unset($Array[$index]);
        }
    }
    return $Array;
}
Ali Farmani
fuente
7

Utilizo el siguiente script para eliminar elementos vacíos de una matriz

for ($i=0; $i<$count($Array); $i++)
  {
    if (empty($Array[$i])) unset($Array[$i]);
  }
concepto w
fuente
7

Solo quiero contribuir con una alternativa a los bucles ... también abordando las brechas en las claves ...

En mi caso, quería mantener las teclas de matriz secuenciales cuando se completaba la operación (no solo números impares, que es lo que estaba mirando. Configurar el código para buscar solo teclas impares me parecía frágil y no era adecuado para el futuro).

Estaba buscando algo más como esto: http://gotofritz.net/blog/howto/removing-empty-array-elements-php/

La combinación de array_filter y array_slice hace el truco.

$example = array_filter($example); $example = array_slice($example,0);

No tengo idea de eficiencias o puntos de referencia, pero funciona.

Chrisdigital
fuente
Creo que array_values ​​tendría el mismo resultado que array_slice. Eso parece más intuitivo en términos de leer el código más tarde y comprender lo que está haciendo.
arlomedia
6
$my = ("0"=>" ","1"=>"5","2"=>"6","3"=>" ");   

foreach ($my as $key => $value) {
    if (is_null($value)) unset($my[$key]);
}

foreach ($my as $key => $value) {
    echo   $key . ':' . $value . '<br>';
} 

salida

1: 5

2: 6

Naitik Shah
fuente
5
foreach($arr as $key => $val){
   if (empty($val)) unset($arr[$key];
}
Mak Ashtekar
fuente
simple, directo!
Richter
5

Solo una línea: Actualización (gracias a @suther):

$array_without_empty_values = array_filter($array);
Mate
fuente
no necesita su segundo parámetro: $ clean_array = array_filter ($ dirty_array);
suther
4

use la array_filterfunción para eliminar valores vacíos:

$linksArray = array_filter($linksArray);
print_r($linksArray);
Ankit Gupta
fuente
Quiere eliminar cadenas en blanco , que no es equivalente a valores vacíos.
Cranio
4

Eliminar elementos de matriz vacíos

function removeEmptyElements(&$element)
{
    if (is_array($element)) {
        if ($key = key($element)) {
            $element[$key] = array_filter($element);
        }

        if (count($element) != count($element, COUNT_RECURSIVE)) {
            $element = array_filter(current($element), __FUNCTION__);
        }

        return $element;
    } else {
        return empty($element) ? false : $element;
    }
}

$data = array(
    'horarios' => array(),
    'grupos' => array(
        '1A' => array(
            'Juan' => array(
                'calificaciones' => array(
                    'Matematicas' => 8,
                    'Español' => 5,
                    'Ingles' => 9,
                ),
                'asistencias' => array(
                    'enero' => 20,
                    'febrero' => 10,
                    'marzo' => '',
                )
            ),
            'Damian' => array(
                'calificaciones' => array(
                    'Matematicas' => 10,
                    'Español' => '',
                    'Ingles' => 9,
                ),
                'asistencias' => array(
                    'enero' => 20,
                    'febrero' => '',
                    'marzo' => 5,
                )
            ),
        ),
        '1B' => array(
            'Mariana' => array(
                'calificaciones' => array(
                    'Matematicas' => null,
                    'Español' => 7,
                    'Ingles' => 9,
                ),
                'asistencias' => array(
                    'enero' => null,
                    'febrero' => 5,
                    'marzo' => 5,
                )
            ),
        ),
    )
);

$data = array_filter($data, 'removeEmptyElements');
var_dump($data);

¡funciona!

iBet7o
fuente
3

Según su método, puede capturar esos elementos en otra matriz y usarlos de la siguiente manera,

foreach($linksArray as $link){
   if(!empty($link)){
      $new_arr[] = $link
   }
}

print_r($new_arr);
Shahrukh Anwar
fuente
1

prueba esto ** ** Ejemplo

$or = array(
        'PersonalInformation.first_name' => $this->request->data['User']['first_name'],
        'PersonalInformation.last_name' => $this->request->data['User']['last_name'],
        'PersonalInformation.primary_phone' => $this->request->data['User']['primary_phone'],
        'PersonalInformation.dob' => $this->request->data['User']['dob'],
        'User.email' => $this->request->data['User']['email'],
    );



 $or = array_filter($or);

    $condition = array(
        'User.role' => array('U', 'P'),
        'User.user_status' => array('active', 'lead', 'inactive'),
        'OR' => $or
    );
Ashish Pathak
fuente
1
¿Que es esto? Hay toneladas de otras respuestas muy relevantes. ¿Qué estás agregando aquí?
Félix Gagnon-Grenier
echa un vistazo a la url, ¡cuál era la pregunta aquí! / * eliminar elemento de matriz vacío * /
Ashish pathak
1

Creo que array_walk es mucho más adecuado aquí

$linksArray = array('name', '        ', '  342', '0', 0.0, null, '', false);

array_walk($linksArray, function(&$v, $k) use (&$linksArray){
    $v = trim($v);
    if ($v == '')
        unset($linksArray[$k]);
});
print_r($linksArray);

Salida:

Array
(
    [0] => name
    [2] => 342
    [3] => 0
    [4] => 0
)
  • Nos aseguramos de que los valores vacíos se eliminen incluso si el usuario agrega más de un espacio
  • También recortamos espacios vacíos de los valores válidos

  • Finalmente, solo (nulo), (Boolean False) y ('') se considerarán cadenas vacías

En cuanto a Falseque está bien eliminarlo, porque AFAIK el usuario no puede enviar valores booleanos.

Lluvia
fuente
0

Con este tipo de cosas, es mucho mejor ser explícito sobre lo que quieres y lo que no quieres.

Ayudará al próximo tipo a no ser sorprendido por el comportamiento array_filter()sin una devolución de llamada. Por ejemplo, terminé con esta pregunta porque olvidé si array_filter()elimina NULLo no. Perdí el tiempo cuando podría haber usado la solución a continuación y obtuve mi respuesta.

Además, la lógica es el lenguaje angnóstico en el sentido de que el código se puede copiar a otro idioma sin tener que entender el comportamiento de una función php como array_filtercuando no se pasa la devolución de llamada.

En mi solución, es claro a simple vista lo que está sucediendo. Elimine un condicional para mantener algo o agregue una nueva condición para filtrar valores adicionales.

Haga caso omiso del uso real de, array_filter()ya que solo le estoy pasando una devolución de llamada personalizada; puede continuar y extraer eso para su propia función si lo desea. Solo lo estoy usando como azúcar para un foreachbucle.

<?php

$xs = [0, 1, 2, 3, "0", "", false, null];

$xs = array_filter($xs, function($x) {
    if ($x === null) { return false; }
    if ($x === false) { return false; }
    if ($x === "") { return false; }
    if ($x === "0") { return false; }
    return true;
});

$xs = array_values($xs); // reindex array   

echo "<pre>";
var_export($xs);

Otro beneficio de este enfoque es que puede dividir los predicados de filtrado en una función abstracta que filtra un solo valor por matriz y construir una solución componible.

Vea este ejemplo y los comentarios en línea para la salida.

<?php

/**
 * @param string $valueToFilter
 *
 * @return \Closure A function that expects a 1d array and returns an array
 *                  filtered of values matching $valueToFilter.
 */
function filterValue($valueToFilter)
{
    return function($xs) use ($valueToFilter) {
        return array_filter($xs, function($x) use ($valueToFilter) {
            return $x !== $valueToFilter;
        });
    };
}

// partially applied functions that each expect a 1d array of values
$filterNull = filterValue(null);
$filterFalse = filterValue(false);
$filterZeroString = filterValue("0");
$filterEmptyString = filterValue("");

$xs = [0, 1, 2, 3, null, false, "0", ""];

$xs = $filterNull($xs);        //=> [0, 1, 2, 3, false, "0", ""]
$xs = $filterFalse($xs);       //=> [0, 1, 2, 3, "0", ""]
$xs = $filterZeroString($xs);  //=> [0, 1, 2, 3, ""]
$xs = $filterEmptyString($xs); //=> [0, 1, 2, 3]

echo "<pre>";
var_export($xs); //=> [0, 1, 2, 3]

Ahora puede crear dinámicamente una función llamada filterer()using pipe()que aplicará estas funciones parcialmente aplicadas por usted.

<?php

/**
 * Supply between 1..n functions each with an arity of 1 (that is, accepts
 * one and only one argument). Versions prior to php 5.6 do not have the
 * variadic operator `...` and as such require the use of `func_get_args()` to
 * obtain the comma-delimited list of expressions provided via the argument
 * list on function call.
 *
 * Example - Call the function `pipe()` like:
 *
 *   pipe ($addOne, $multiplyByTwo);
 *
 * @return closure
 */
function pipe()
{
    $functions = func_get_args(); // an array of callable functions [$addOne, $multiplyByTwo]
    return function ($initialAccumulator) use ($functions) { // return a function with an arity of 1
        return array_reduce( // chain the supplied `$arg` value through each function in the list of functions
            $functions, // an array of functions to reduce over the supplied `$arg` value
            function ($accumulator, $currFn) { // the reducer (a reducing function)
                return $currFn($accumulator);
            },
            $initialAccumulator
        );
    };
}

/**
 * @param string $valueToFilter
 *
 * @return \Closure A function that expects a 1d array and returns an array
 *                  filtered of values matching $valueToFilter.
 */
function filterValue($valueToFilter)
{
    return function($xs) use ($valueToFilter) {
        return array_filter($xs, function($x) use ($valueToFilter) {
            return $x !== $valueToFilter;
        });
    };
}

$filterer = pipe(
    filterValue(null),
    filterValue(false),
    filterValue("0"),
    filterValue("")
);

$xs = [0, 1, 2, 3, null, false, "0", ""];
$xs = $filterer($xs);

echo "<pre>";
var_export($xs); //=> [0, 1, 2, 3]
puiu
fuente