Comment puis-je imploser un tableau tout en sautant des éléments de tableau vides?

94

Perl join()ignore (saute) les valeurs de tableau vides; PHP implode()ne semble pas.

Supposons que j'ai un tableau:

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

donne:

one---four--six

au lieu de (IMHO le préférable):

one-four-six

Y a-t-il d'autres éléments intégrés avec le comportement que je recherche? Ou est-ce que ça va être un jobbie personnalisé?

Tom Auger
la source
2
Vous vous trompez sur le comportement de Perl. joinn'ignore pas les éléments non définis. En fait, ils entraînent un avertissement. $a[0]="a"; $a[2]="c"; say join "-",@a;affiche Use of uninitialized value within @a in join or stringet a--c. On peut utiliser join '-', grep !defined, ...pour ignorer les valeurs non définies. grep !length,fera des chaînes vides.
ikegami

Réponses:

210

Vous pouvez utiliser array_filter():

Si aucun rappel n'est fourni, toutes les entrées d' entrée égales à FALSE(voir conversion en booléen ) seront supprimées.

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

Évidemment, cela ne fonctionnera pas si vous avez 0(ou toute autre valeur évaluée à false) dans votre tableau et que vous souhaitez le conserver. Mais alors vous pouvez fournir votre propre fonction de rappel.

Félix Kling
la source
5
Cela voudrait-il dire cela false, et 0sont également rejetés?
Ben
1
@maz: Oui, mais vous pouvez toujours fournir votre propre rappel. empty, comme vous l'utilisez, traitera également 0et falsecomme false(et le supprimera) btw.
Felix Kling
3
+1, mais il doit être mentionné que array_filter()par des filtres par défaut hors tout false, null, chaîne vide ( « ») et 0.
Tadeck
1
@Tadeck: Oui, suivez simplement le lien dans le devis. Encore plus de valeurs sont considérées comme false: tableau vide, 0.0et "0".
Felix Kling
@Felix: Je le savais - je voulais juste le souligner pour les nouveaux utilisateurs de PHP;) Quoi qu'il en soit: merci
Tadeck
9

Je suppose que vous ne pouvez pas le considérer comme intégré (car la fonction s'exécute avec une fonction définie par l'utilisateur), mais vous pouvez toujours utiliser array_filter .
Quelque chose comme:

function rempty ($var)
{
    return !($var == "" || $var == null);
}
$string = implode('-',array_filter($array, 'rempty'));
Ben
la source
1
L'utilisation emptya le même effet que de ne passer aucun rappel. Edit: Vous devez annuler la valeur de retour. Sinon, seuls les éléments vides seront retournés;) (en fait, utiliser emptycomme vous le
Felix Kling
1
Ouais, c'est en arrière. Mais vous m'avez donné la bonne idéeimplode('-', array_filter($ary, create_function('$a', 'return $a!="";')));
Tom Auger
3

La manière dont vous devez mettre en œuvre votre filtre dépend uniquement de ce que vous voyez comme "vide".

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
la source
3

Pour supprimer null, false, emptychaîne mais conserver 0, etc. utilisation fonct. ' strlen'

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

affichera:

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

Sur la base de ce que je peux trouver, je dirais que les chances sont, il n'y a vraiment aucun moyen d'utiliser un PHP intégré pour cela. Mais vous pourriez probablement faire quelque chose du genre:

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
la source
1

Essaye ça:

$result = array();

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

implode('-', $result);
Jérémie
la source
1
$array = ["one", NULL, "two", NULL, "three"];
$string = implode("-", array_diff($array, [NULL]));
echo $string;

Retour one-two-three

Ryan Prescott
la source
-1

array_fileter() semble être la voie acceptée ici, et reste probablement la réponse la plus robuste à ce sujet.

Cependant, ce qui suit fonctionnera également si vous pouvez garantir que le caractère "glue" n'existe pas déjà dans les chaînes de chaque élément du tableau (ce qui serait donné dans la plupart des circonstances pratiques - sinon vous ne seriez pas en mesure de distinguer la colle des données réelles dans le tableau):

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

Essaye ça:

if(isset($array))  $array = implode(",", (array)$array);
user2775080
la source
Vous pouvez utiliser isset () pour éviter les avertissements.
user2775080
Je ne suis pas sûr de savoir comment isset()ou comment le casting du tableau d'entrée arrayrépond à l'une des préoccupations du message d'origine?
Tom Auger
1
Ce n'est pas une solution. La conversion en (tableau) ne supprime pas les éléments vides du tableau.
mjwunderlich