Làm cách nào tôi có thể mã hóa một mảng trong khi bỏ qua các mục mảng trống?


94

Perl's join()bỏ qua (bỏ qua) các giá trị mảng trống; PHP implode()có vẻ như không.

Giả sử tôi có một mảng:

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

sản lượng:

one---four--six

thay vì (IMHO thích hợp hơn):

one-four-six

Bất kỳ tích hợp sẵn nào khác với hành vi mà tôi đang tìm kiếm? Hay nó sẽ trở thành một jobbie tùy chỉnh?


2
Bạn đã sai về hành vi của Perl. joinkhông bỏ qua các phần tử không xác định. Trên thực tế, chúng dẫn đến một cảnh báo. $a[0]="a"; $a[2]="c"; say join "-",@a;hiển thị Use of uninitialized value within @a in join or stringa--c. Người ta có thể sử dụng join '-', grep !defined, ...để bỏ qua các giá trị không xác định. grep !length,sẽ làm chuỗi trống.
ikegami

Câu trả lời:


210

Bạn có thể sử dụng array_filter():

Nếu không có lệnh gọi lại nào được cung cấp, tất cả các mục nhập của đầu vào bằng FALSE(xem chuyển đổi thành boolean ) sẽ bị xóa.

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

Rõ ràng điều này sẽ không hoạt động nếu bạn có 0(hoặc bất kỳ giá trị nào khác được đánh giá là false) trong mảng của bạn và bạn muốn giữ nó. Nhưng sau đó bạn có thể cung cấp chức năng gọi lại của riêng mình.


5
Điều đó có nghĩa là false, và 0cũng bị loại bỏ?
Ben

1
@maz: Có, nhưng bạn luôn có thể cung cấp lệnh gọi lại của riêng mình. empty, khi bạn sử dụng nó, cũng sẽ coi 0falsenhư false(và loại bỏ nó) btw.
Felix Kling

3
+1, nhưng nó phải được đề cập, array_filter()theo mặc định lọc bỏ mọi false,, nullchuỗi rỗng ('') và 0.
Tadeck

1
@Tadeck: Vâng, chỉ cần theo liên kết trong báo giá. Thậm chí nhiều giá trị hơn được coi là false: mảng trống 0.0"0".
Felix Kling

@Felix: Tôi biết điều đó - chỉ muốn nhấn mạnh nó cho những người mới sử dụng PHP;) Dù sao: cảm ơn bạn
Tadeck

9

Tôi cho rằng bạn không thể coi nó được tích hợp sẵn (vì hàm đang chạy với một hàm do người dùng xác định), nhưng bạn luôn có thể sử dụng array_filter .
Cái gì đó như:

function rempty ($var)
{
    return !($var == "" || $var == null);
}
$string = implode('-',array_filter($array, 'rempty'));

1
Việc sử dụng emptycó tác dụng giống như việc không gọi lại gì cả. Chỉnh sửa: Bạn phải phủ định giá trị trả về. Nếu không, chỉ các phần tử trống sẽ được trả về;) (thực sự sử dụng emptynhư bạn đã làm trước đây cũng sai)
Felix Kling

1
Vâng, đó là lạc hậu. Nhưng bạn đã cho tôi ý tưởng đúngimplode('-', array_filter($ary, create_function('$a', 'return $a!="";')));
Tom Auger

3

Bạn nên triển khai bộ lọc như thế nào chỉ phụ thuộc vào những gì bạn thấy là "trống rỗng".

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

Để loại bỏ null, false, emptychuỗi nhưng giữ gìn 0, vv sử dụng Func. ' strlen'

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

sẽ xuất:

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

1

Dựa trên những gì tôi có thể tìm thấy, tôi muốn nói rằng rất có thể, không có bất kỳ cách nào để sử dụng PHP được tích hợp sẵn cho việc đó. Nhưng bạn có thể làm điều gì đó dọc theo dòng này:

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

Thử cái này:

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

Lợi nhuận one-two-three


-1

array_fileter() dường như là cách được chấp nhận ở đây, và có lẽ vẫn là câu trả lời chắc chắn nhất tbh.

Tuy nhiên, những điều sau đây cũng sẽ hoạt động nếu bạn có thể đảm bảo rằng ký tự "keo" không tồn tại trong các chuỗi của mỗi phần tử mảng (sẽ là ký tự được cho trong hầu hết các trường hợp thực tế - nếu không bạn sẽ không thể phân biệt được keo từ dữ liệu thực tế trong mảng):

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

-3

Thử cái này:

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

Bạn có thể muốn sử dụng Isset () để ngăn cảnh báo.
user2775080

Tôi không chắc về cách isset()hoặc cách truyền mảng đầu vào như arraygiải quyết bất kỳ mối quan tâm nào của bài đăng gốc?
Tom Auger

1
Đây không phải là một giải pháp. Truyền tới (mảng) không xóa các mục trống khỏi mảng.
mjwunderlich
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.