¿Cómo puedo implosionar una matriz mientras omito elementos de matriz vacíos?


94

Perl join()ignora (omite) valores de matriz vacíos; PHPimplode() no parece.

Supongamos que tengo una matriz:

$array = array('one', '', '', 'four', '', 'six');
implode('-', $array);

rinde:

one---four--six

en lugar de (en mi humilde opinión, lo preferible):

one-four-six

¿Algún otro incorporado con el comportamiento que estoy buscando? ¿O será un jobbie personalizado?


2
Estás equivocado sobre el comportamiento de Perl. joinno omite elementos indefinidos. De hecho, resultan en una advertencia. $a[0]="a"; $a[2]="c"; say join "-",@a;muestra Use of uninitialized value within @a in join or stringy a--c. Se puede usar join '-', grep !defined, ...para omitir valores indefinidos. grep !length,Hará cadenas vacías.
ikegami

Respuestas:


210

Puede utilizar array_filter():

Si no se proporciona ninguna devolución de llamada , se eliminarán todas las entradas de entrada igual a FALSE(ver conversión a booleano ).

implode('-', array_filter($array));

Obviamente, esto no funcionará si tiene 0(o cualquier otro valor que evalúe false) en su matriz y desea conservarlo. Pero luego puede proporcionar su propia función de devolución de llamada.


5
¿Eso significaría eso false, y 0también se desechan?
Ben

1
@maz: Sí, pero siempre puede proporcionar su propia devolución de llamada. empty, a medida que lo use, también lo tratará 0y falsecomo false(y lo eliminará) por cierto.
Felix Kling

3
1, pero tiene que ser mencionado, que array_filter()mediante filtros por defecto fuera de cada false, null, cadena vacía ( '') y 0.
Tadeck

1
@Tadeck: Sí, solo siga el enlace en la cita. Incluso más valores se consideran como false: matriz vacía 0.0y "0".
Felix Kling

@Felix: Lo sabía, solo quería enfatizarlo para las personas nuevas en PHP;) De todos modos: gracias
Tadeck

9

Supongo que no puede considerarlo integrado (porque la función se ejecuta con una función definida por el usuario), pero siempre puede usar array_filter .
Algo como:

function rempty ($var)
{
    return !($var == "" || $var == null);
}
$string = implode('-',array_filter($array, 'rempty'));

1
El uso emptytiene el mismo efecto que no pasar ninguna devolución de llamada. Editar: tienes que negar el valor de retorno. De lo contrario, solo se devolverán los elementos vacíos;) (en realidad, usar emptycomo lo hizo antes también fue incorrecto)
Felix Kling

1
Sí, eso es al revés. Pero me diste la idea correctaimplode('-', array_filter($ary, create_function('$a', 'return $a!="";')));
Tom Auger

3

La forma en que debe implementar su filtro solo depende de lo que vea como "vacío".

function my_filter($item)
{
    return !empty($item); // Will discard 0, 0.0, '0', '', NULL, array() of FALSE
    // Or...
    return !is_null($item); // Will only discard NULL
    // or...
    return $item != "" && $item !== NULL; // Discards empty strings and NULL
    // or... whatever test you feel like doing
}

function my_join($array)
{
    return implode('-',array_filter($array,"my_filter"));
} 

3

Para quitar null, false, emptycadena, pero preservar 0, etc. uso func. ' strlen'

$arr = [null, false, "", 0, "0", "1", "2", "false"];
print_r(array_filter($arr, 'strlen'));

dará salida:

//Array ( [3] => 0 [4] => 0 [5] => 1 [6] => 2 [7] => false )

1

Según lo que puedo encontrar, diría que lo más probable es que realmente no haya ninguna forma de usar un PHP integrado para eso. Pero probablemente podrías hacer algo como esto:

function implode_skip_empty($glue,$arr) {
      $ret = "";
      $len = sizeof($arr);
      for($i=0;$i<$len;$i++) {
          $val = $arr[$i];    
          if($val == "") {
              continue;
          } else {
            $ret .= $arr.($i+1==$len)?"":$glue;
          }
      }
      return $ret;
}

1

Prueba esto:

$result = array();

foreach($array as $row) { 
   if ($row != '') {
   array_push($result, $row); 
   }
}

implode('-', $result);

1
$array = ["one", NULL, "two", NULL, "three"];
$string = implode("-", array_diff($array, [NULL]));
echo $string;

Devoluciones one-two-three


-1

array_fileter() parece ser la forma aceptada aquí, y probablemente sigue siendo la respuesta más robusta por cierto.

Sin embargo, lo siguiente también funcionará si puede garantizar que el carácter "pegamento" no existe ya en las cadenas de cada elemento de la matriz (lo que sería un hecho en la mayoría de las circunstancias prácticas; de lo contrario, no podría distinguir el pegamento de los datos reales en la matriz):

$array = array('one', '', '', 'four', '', 'six');
$str   = implode('-', $array);
$str   = preg_replace ('/(-)+/', '\1', $str);

-3

Prueba esto:

if(isset($array))  $array = implode(",", (array)$array);

Es posible que desee utilizar isset () para evitar advertencias.
user2775080

No estoy seguro de cómo isset()o convertir la matriz de entrada como arrayaborda alguna de las preocupaciones de la publicación original.
Tom Auger

1
Esta no es una solución. La conversión a (matriz) no elimina los elementos vacíos de la matriz.
mjwunderlich
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.