¿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?

Tom Auger
fuente
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.

Felix Kling
fuente
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'));
Ben
fuente
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"));
} 
Thomas Hupkens
fuente
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 )
Ali Varli
fuente
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;
}
ozzmotik
fuente
1

Prueba esto:

$result = array();

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

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

Devoluciones one-two-three

Ryan Prescott
fuente
-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);
carro de caballos
fuente
-3

Prueba esto:

if(isset($array))  $array = implode(",", (array)$array);
usuario2775080
fuente
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