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?


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.


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'));

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"));
} 

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 )

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;
}

1

Coba ini:

$result = array();

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

implode('-', $result);

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

Kembali one-two-three


-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);

-3

Coba ini:

if(isset($array))  $array = implode(",", (array)$array);

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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.