How can I implode an array while skipping empty array items?
Asked Answered
C

9

116

Perl's join() ignores (skips) empty array values; PHP's implode() does not appear to.

Suppose I have an array:

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

yields:

one---four--six

instead of (IMHO the preferable):

one-four-six

Any other built-ins with the behaviour I'm looking for? Or is it going to be a custom jobbie?

Celebration answered 12/5, 2011 at 22:49 Comment(1)
You're wrong about Perl's behaviour. join doesn't skip undefined elements. In fact, they result in a warning. $a[0]="a"; $a[2]="c"; say join "-",@a; displays Use of uninitialized value within @a in join or string and a--c. One can use join '-', grep !defined, ... to skip undefined values. grep !length, will do empty strings.Huey
S
247

You can use array_filter():

If no callback is supplied, all entries of input equal to FALSE (see converting to boolean) will be removed.

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

Obviously this will not work if you have 0 (or any other value that evaluates to false) in your array and you want to keep it. But then you can provide your own callback function.

Stook answered 12/5, 2011 at 22:52 Comment(6)
Would that mean that false, and 0 are also thrown out?Opportune
@maz: Yes, but you can always provide your own callback. empty, as you use it, will also treat 0 and false as false (and remove it) btw.Stook
+1, but it has to be mentioned, that array_filter() by default filters off every false, null, empty string ('') and 0.Wien
@Tadeck: Yes, just follow the link in the quote. Even more values are considered as false: empty array, 0.0 and "0".Stook
@Felix: I knew it - just wanted to stress it for people new in PHP ;) Anyway: thank youWien
Nice trick - didn't know array_filter can work without callback :)Arcane
O
9

I suppose you can't consider it built in (because the function is running with a user defined function), but you could always use array_filter.
Something like:

function rempty ($var)
{
    return !($var == "" || $var == null);
}
$string = implode('-',array_filter($array, 'rempty'));
Opportune answered 12/5, 2011 at 22:53 Comment(2)
Using empty has the same effect as passing no callback at all. Edit: You have to negate the return value. Otherwise only empty elements will be returned ;) (actually using empty as you did before was also wrong)Stook
Yeah, that's backward. But you gave me the right idea implode('-', array_filter($ary, create_function('$a', 'return $a!="";')));Celebration
P
8

To remove null, false, empty string but preserve 0, etc. use func. 'strlen'

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

will output:

//Array ( [3] => 0 [4] => 0 [5] => 1 [6] => 2 [7] => false )
Postmillennialism answered 5/4, 2018 at 14:48 Comment(0)
B
3

How you should implement you filter only depends on what you see as "empty".

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"));
} 
Baxter answered 12/5, 2011 at 23:10 Comment(0)
A
2
$array = ["one", NULL, "two", NULL, "three"];
$string = implode("-", array_diff($array, [NULL]));
echo $string;

Returns one-two-three

Antifebrile answered 29/6, 2020 at 0:38 Comment(0)
M
1

Based on what I can find, I'd say chances are, there isn't really any way to use a PHP built in for that. But you could probably do something along the lines of this:

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;
}
Micmac answered 12/5, 2011 at 22:56 Comment(0)
H
1

Try this:

$result = array();

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

implode('-', $result);
Heydon answered 12/5, 2011 at 22:56 Comment(0)
B
-1

array_fileter() seems to be the accepted way here, and is probably still the most robust answer tbh.

However, the following will also work if you can guarantee that the "glue" character doesn't already exist in the strings of each array element (which would be a given under most practical circumstances -- otherwise you wouldn't be able to distinguish the glue from the actual data in the array):

$array = array('one', '', '', 'four', '', 'six');
$str   = implode('-', $array);
$str   = preg_replace ('/(-)+/', '\1', $str);
Bobstay answered 4/11, 2017 at 13:5 Comment(0)
K
-3

Try this:

if(isset($array))  $array = implode(",", (array)$array);
Kela answered 2/12, 2013 at 8:0 Comment(3)
You might want to use isset() to prevent warnings.Kela
I'm not sure how isset() or casting the input array as array addresses any of the concerns of the original post?Celebration
This is not a solution. Casting to (array) does not remove empty items from the array.Lyingin

© 2022 - 2024 — McMap. All rights reserved.