Bagaimana saya bisa meledakkan array sambil melewatkan item array kosong?

95

Perl join()mengabaikan (melewatkan) nilai array kosong; PHP implode()tampaknya tidak.

Misalkan saya memiliki array:

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

hasil:

one---four--six

daripada (IMHO lebih disukai):

one-four-six

Adakah bawaan lainnya dengan perilaku yang saya cari? Atau akan menjadi pekerja khusus?

Tom Auger
sumber
2
Anda salah tentang perilaku Perl. jointidak melewatkan elemen yang tidak ditentukan. Faktanya, mereka menghasilkan peringatan. $a[0]="a"; $a[2]="c"; say join "-",@a;menampilkan Use of uninitialized value within @a in join or stringdan a--c. Satu dapat digunakan join '-', grep !defined, ...untuk melewati nilai yang tidak ditentukan. grep !length,akan melakukan string kosong.
ikegami

Jawaban:

211

Anda dapat menggunakan array_filter():

Jika tidak ada callback yang diberikan, semua entri input yang sama dengan FALSE(lihat mengubah ke boolean ) akan dihapus.

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

Jelas ini tidak akan berfungsi jika Anda memiliki 0(atau nilai lain yang dievaluasi ke false) dalam larik Anda dan Anda ingin menyimpannya. Tapi kemudian Anda bisa menyediakan fungsi panggilan balik Anda sendiri.

Felix Kling
sumber
5
Apakah itu berarti demikian false, dan 0juga dibuang?
Ben
1
@maz: Ya, tetapi Anda selalu dapat memberikan panggilan balik Anda sendiri. empty, saat Anda menggunakannya, juga akan memperlakukan 0dan falsesebagai false(dan menghapusnya) btw.
Felix Kling
3
+1, tetapi harus disebutkan, bahwa array_filter()secara default menyaring setiap false,, nullstring kosong ('') dan 0.
Tadeck
1
@Tadeck: Ya, cukup ikuti tautan di kutipan. Bahkan lebih banyak nilai dianggap sebagai false: larik kosong, 0.0dan "0".
Felix Kling
@Felix: Saya tahu itu - hanya ingin menekankannya untuk orang-orang yang baru mengenal PHP;) Bagaimanapun: terima kasih
Tadeck
9

Saya kira Anda tidak dapat menganggapnya built in (karena fungsinya berjalan dengan fungsi yang ditentukan pengguna), tetapi Anda selalu dapat menggunakan array_filter .
Sesuatu seperti:

function rempty ($var)
{
    return !($var == "" || $var == null);
}
$string = implode('-',array_filter($array, 'rempty'));
Ben
sumber
1
Penggunaan emptymemiliki efek yang sama dengan tidak meneruskan callback sama sekali. Edit: Anda harus meniadakan nilai yang dikembalikan. Jika tidak, hanya elemen kosong yang akan dikembalikan;) (sebenarnya menggunakan emptyseperti yang Anda lakukan sebelumnya juga salah)
Felix Kling
1
Ya, itu mundur. Tapi Anda memberi saya ide yang benarimplode('-', array_filter($ary, create_function('$a', 'return $a!="";')));
Tom Auger
3

Bagaimana Anda harus menerapkan filter Anda hanya bergantung pada apa yang Anda lihat sebagai "kosong".

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

Untuk menghapus null, false, emptystring tetapi melestarikan 0, dll penggunaan func. ' strlen'

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

akan mengeluarkan:

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

Berdasarkan apa yang dapat saya temukan, menurut saya kemungkinan besar, sebenarnya tidak ada cara untuk menggunakan PHP bawaan untuk itu. Tetapi Anda mungkin bisa melakukan sesuatu seperti ini:

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

Coba ini:

$result = array();

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

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

Kembali one-two-three

Ryan Prescott
sumber
-1

array_fileter() tampaknya cara yang diterima di sini, dan mungkin masih merupakan jawaban yang paling kuat tbh.

Namun, hal berikut juga akan berfungsi jika Anda dapat menjamin bahwa karakter "perekat" belum ada di string setiap elemen array (yang akan diberikan dalam keadaan paling praktis - jika tidak, Anda tidak akan dapat membedakan lem dari data aktual dalam larik):

$array = array('one', '', '', 'four', '', 'six');
$str   = implode('-', $array);
$str   = preg_replace ('/(-)+/', '\1', $str);
kereta kuda sebelumnya
sumber
-3

Coba ini:

if(isset($array))  $array = implode(",", (array)$array);
pengguna2775080
sumber
Anda mungkin ingin menggunakan isset () untuk mencegah peringatan.
pengguna2775080
Saya tidak yakin bagaimana isset()atau mentransmisikan array input sebagai arrayalamat salah satu kekhawatiran dari posting asli?
Tom Auger
1
Ini bukanlah solusi. Mentransmisikan ke (larik) tidak menghapus item kosong dari larik.
mjwunderlich