Jak mogę implodować tablicę, pomijając puste elementy tablicy?

95

Perl join()ignoruje (pomija) puste wartości tablicowe; PHPimplode() nie wydaje się.

Załóżmy, że mam tablicę:

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

plony:

one---four--six

zamiast (preferowane IMHO):

one-four-six

Czy są jakieś inne wbudowane funkcje, których szukam? A może będzie to niestandardowy pracownik?

Tom Auger
źródło
2
Mylisz się co do zachowania Perla. joinnie pomija niezdefiniowanych elementów. W rzeczywistości skutkują ostrzeżeniem. $a[0]="a"; $a[2]="c"; say join "-",@a;wyświetlacze Use of uninitialized value within @a in join or stringi a--c. Można użyć join '-', grep !defined, ...do pominięcia niezdefiniowanych wartości. grep !length,zrobi puste łańcuchy.
ikegami

Odpowiedzi:

212

Możesz użyć array_filter():

Jeśli nie podano wywołania zwrotnego , wszystkie wpisy wejścia równe FALSE(zobacz konwersję na wartość logiczną ) zostaną usunięte.

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

Oczywiście to nie zadziała, jeśli masz 0(lub jakąkolwiek inną wartość, której wynikiem jest false) w swojej tablicy i chcesz ją zachować. Ale wtedy możesz udostępnić własną funkcję wywołania zwrotnego.

Felix Kling
źródło
5
Czy to oznaczałoby to false, a 0także zostałyby wyrzucone?
Ben
1
@maz: Tak, ale zawsze możesz podać własne oddzwonienie. empty, jak go używasz, będzie również traktować 0i falsejako false(i usuwać) btw.
Felix Kling
3
+1, ale należy wspomnieć, że array_filter()przez filtry domyślnie wyłączone każdy false, null, pusty ciąg ( „”) oraz 0.
Tadeck
1
@ Tadeck: Tak, po prostu kliknij link w wycenie. Jeszcze więcej wartości jest rozważanych jako false: pusta tablica 0.0i "0".
Felix Kling
@Felix: Wiedziałem - po prostu chciałem to podkreślić dla ludzi nowych w PHP;) W każdym razie: dziękuję
Tadeck
9

Przypuszczam, że nie można traktować tego jako wbudowanego (ponieważ funkcja działa z funkcją zdefiniowaną przez użytkownika), ale zawsze można użyć array_filter .
Coś jak:

function rempty ($var)
{
    return !($var == "" || $var == null);
}
$string = implode('-',array_filter($array, 'rempty'));
Ben
źródło
1
Używanie emptyma taki sam efekt, jak przekazywanie żadnego wywołania zwrotnego. Edycja: Musisz zanegować wartość zwracaną. W przeciwnym razie zostaną zwrócone tylko puste elementy;) (użycie emptytak jak wcześniej było również błędne)
Felix Kling
1
Tak, to jest zacofane. Ale dałeś mi dobry pomysłimplode('-', array_filter($ary, create_function('$a', 'return $a!="";')));
Tom Auger
3

Sposób implementacji filtru zależy tylko od tego, co widzisz jako „puste”.

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
źródło
3

Aby usunąć null, false, emptyciąg, ale zachować 0itd użytkowania func. ' strlen'

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

wyświetli:

//Array ( [3] => 0 [4] => 0 [5] => 1 [6] => 2 [7] => false )
Ali Varli
źródło
1

Na podstawie tego, co mogę znaleźć, powiedziałbym, że są szanse, tak naprawdę nie ma sposobu, aby użyć wbudowanego PHP do tego. Ale prawdopodobnie mógłbyś zrobić coś w ten sposób:

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
źródło
1

Spróbuj tego:

$result = array();

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

implode('-', $result);
Jeremy
źródło
1
$array = ["one", NULL, "two", NULL, "three"];
$string = implode("-", array_diff($array, [NULL]));
echo $string;

Zwroty one-two-three

Ryan Prescott
źródło
-1

array_fileter() wydaje się być tutaj akceptowanym sposobem i prawdopodobnie nadal jest najbardziej solidną odpowiedzią tbh.

Jednak poniższe będzie również działać, jeśli możesz zagwarantować, że znak „klej” nie istnieje już w łańcuchach każdego elementu tablicy (który byłby podany w większości praktycznych okoliczności - w przeciwnym razie nie byłbyś w stanie odróżnić klej z rzeczywistych danych w tablicy):

$array = array('one', '', '', 'four', '', 'six');
$str   = implode('-', $array);
$str   = preg_replace ('/(-)+/', '\1', $str);
cartbeforehorse
źródło
-3

Spróbuj tego:

if(isset($array))  $array = implode(",", (array)$array);
user2775080
źródło
Możesz chcieć użyć isset (), aby zapobiec ostrzeżeniom.
user2775080
Nie jestem pewien, jak isset()lub rzutowanie tablicy wejściowej jest odpowiedzią na arrayktórekolwiek z obaw oryginalnego postu?
Tom Auger
1
To nie jest rozwiązanie. Rzutowanie na (tablica) nie usuwa pustych elementów z tablicy.
mjwunderlich