Wie kann ich ein Array implodieren, während ich leere Array-Elemente überspringe?

94

Perl join()ignoriert (überspringt) leere Array-Werte; PHPs implode()scheinen nicht.

Angenommen, ich habe ein Array:

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

Ausbeuten:

one---four--six

statt (IMHO das vorzuziehen):

one-four-six

Gibt es noch andere integrierte Funktionen mit dem von mir gesuchten Verhalten? Oder wird es ein Custom Jobbie sein?

Tom Auger
quelle
2
Du liegst falsch in Perls Verhalten. joinüberspringt keine undefinierten Elemente. In der Tat führen sie zu einer Warnung. $a[0]="a"; $a[2]="c"; say join "-",@a;zeigt Use of uninitialized value within @a in join or stringund a--c. Man kann join '-', grep !defined, ...undefinierte Werte überspringen. grep !length,macht leere Strings.
Ikegami

Antworten:

209

Sie können verwenden array_filter():

Wenn keine Rückrufzugeführt wird, wird alle Einträge des Eingangs gleich zu FALSE(siehe zum Umwandeln boolean ) wird entfernt.

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

Dies funktioniert natürlich nicht, wenn Sie 0(oder einen anderen Wert, der ausgewertet wird false) in Ihrem Array haben und diesen beibehalten möchten. Aber dann können Sie Ihre eigene Rückruffunktion bereitstellen.

Felix Kling
quelle
5
Würde das das bedeuten falseund 0auch rausgeworfen werden?
Ben
1
@maz: Ja, aber Sie können jederzeit Ihren eigenen Rückruf bereitstellen. empty, wie Sie es verwenden, wird auch 0und falseals false(und entfernen Sie es) übrigens behandeln.
Felix Kling
3
1, aber es muss erwähnt werden, dass array_filter()durch Standardfilter aus jedem false, null, leerer Zeichenfolge ( ‚‘) und 0.
Tadeck
1
@Adeck: Ja, folge einfach dem Link im Zitat. Noch mehr Werte werden berücksichtigt als false: leeres Array 0.0und "0".
Felix Kling
@ Felix: Ich wusste es - wollte es nur für Leute betonen, die neu in PHP sind;) Wie auch immer: Danke
Tadeck
9

Ich nehme an, Sie können es nicht als integriert betrachten (da die Funktion mit einer benutzerdefinierten Funktion ausgeführt wird), aber Sie können immer array_filter verwenden .
Etwas wie:

function rempty ($var)
{
    return !($var == "" || $var == null);
}
$string = implode('-',array_filter($array, 'rempty'));
Ben
quelle
1
Die Verwendung emptyhat den gleichen Effekt wie das Übergeben eines Rückrufs. Bearbeiten: Sie müssen den Rückgabewert negieren. Andernfalls werden nur leere Elemente zurückgegeben;) (die tatsächliche Verwendung emptywie zuvor war ebenfalls falsch)
Felix Kling
1
Ja, das ist rückwärts. Aber du hast mir die richtige Idee gegebenimplode('-', array_filter($ary, create_function('$a', 'return $a!="";')));
Tom Auger
3

Wie Sie Ihren Filter implementieren sollten, hängt nur davon ab, was Sie als "leer" betrachten.

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
quelle
3

Zu entfernen null, false, emptyString aber bewahren 0, usw. Verwendung Func. ' strlen'

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

wird ausgegeben:

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

Basierend auf dem, was ich finden kann, würde ich sagen, dass es wahrscheinlich keine Möglichkeit gibt, ein dafür eingebautes PHP zu verwenden. Aber Sie könnten wahrscheinlich etwas in dieser Richtung tun:

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
quelle
1

Versuche dies:

$result = array();

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

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

Kehrt zurück one-two-three

Ryan Prescott
quelle
-1

array_fileter() scheint hier der akzeptierte Weg zu sein und ist wahrscheinlich immer noch die robusteste Antwort tbh.

Das Folgende funktioniert jedoch auch, wenn Sie sicherstellen können, dass das Zeichen "Kleben" nicht bereits in den Zeichenfolgen der einzelnen Array-Elemente vorhanden ist (was unter den meisten praktischen Umständen gegeben wäre - andernfalls könnten Sie nicht unterscheiden der Kleber aus den tatsächlichen Daten im Array):

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

Versuche dies:

if(isset($array))  $array = implode(",", (array)$array);
user2775080
quelle
Möglicherweise möchten Sie isset () verwenden, um Warnungen zu verhindern.
user2775080
Ich bin mir nicht sicher, wie isset()oder wie das Eingabearray arrayeines der Probleme des ursprünglichen Beitrags umgeht.
Tom Auger
1
Dies ist keine Lösung. Beim Casting in (Array) werden keine leeren Elemente aus dem Array entfernt.
mjwunderlich