Kiểm tra mảng trống: đếm so với trống


98

Câu hỏi về ' Làm thế nào để biết một mảng PHP trống ' đã khiến tôi nghĩ đến câu hỏi này

Có lý do gì countnên được sử dụng thay vì emptykhi xác định xem một mảng có trống hay không?

Suy nghĩ cá nhân của tôi sẽ là nếu 2 tương đương với trường hợp mảng trống mà bạn nên sử dụng emptyvì nó đưa ra câu trả lời boolean cho một câu hỏi boolean. Từ câu hỏi được liên kết ở trên, có vẻ như đó count($var) == 0là phương pháp phổ biến. Đối với tôi, mặc dù đúng về mặt kỹ thuật, không có ý nghĩa gì. Vd: Q: $ var, bạn có trống không? Đáp: 7 . Hừm ...

Có lý do gì tôi nên sử dụng count == 0thay thế hay chỉ là vấn đề sở thích cá nhân?

Như được chỉ ra bởi những người khác trong nhận xét cho một câu trả lời hiện đã bị xóa, countsẽ có tác động đến hiệu suất đối với các mảng lớn vì nó sẽ phải đếm tất cả các phần tử, trong khi emptycó thể dừng lại ngay khi biết nó không trống. Vì vậy, nếu chúng cho kết quả tương tự trong trường hợp này, nhưng countcó khả năng không hiệu quả, tại sao chúng ta lại sử dụng count($var) == 0?


Tôi cho rằng ý định của bạn là giới hạn cuộc trò chuyện chỉ dành riêng cho các mảng, nhưng có thể đáng chú ý là trò chơi thay đổi hoàn toàn nếu bạn đang làm việc với các đối tượng (ví dụ: triển khai Countable, Iterator, v.v.).

8
Một mảng trống bằng falsetrong PHP - không cần empty()hoặc count().
Cobby

Xin vui lòng mã @Cobby.
TheRealChx101

@ TheRealChx101 Như trong, chỉ cần làm: if (!$myArray) { echo "array is empty"; } sandbox.onlinephpfunctions.com/code/…
Cobby

Ngày nay, tùy chọn phổ biến trong câu hỏi được liên kết đang sử dụng empty().
PhoneixS

Câu trả lời:


97

Tôi thường sử dụng empty. Tôi không chắc tại sao mọi người thực sự sẽ sử dụng số đếm - Nếu mảng lớn thì số lượng mất nhiều thời gian hơn / có nhiều chi phí hơn. Nếu bạn chỉ cần biết mảng có trống hay không thì hãy sử dụng rỗng.


4
Các hàm này thực sự khác nhau khi mảng không trống.
Jacco

2
@Jacco: Tôi không phản đối điều đó. Nhưng nếu bạn đang kiểm tra nó trống, tôi không thấy nó có liên quan gì - đó là một câu hỏi với kết quả boolean là hàm sẽ trả về. Liên quan đến những gì được coi là trống trong không thấy những tiêu chí đó sẽ tạo ra câu trả lời sai như thế nào trừ khi var thử nghiệm của bạn không phải là một mảng trong trường hợp đó là một vấn đề hoàn toàn khác.
prodigitalson

23
@prodigitalson Tôi muốn nói rằng số lượng là O(1), vì PHP lưu trữ số lượng phần tử bên trong. Hãy xem câu trả lời này stackoverflow.com/a/5835419/592454
elitalon

4
@eliton: nhưng vẫn còn - ngay cả khi không có hoặc không có sự khác biệt nhỏ về hiệu suất tại sao lại sử dụng số nếu bạn không cần số?
prodigitalson

4
rỗng () là quá tha thứ cho các lỗi. Tôi vừa dành 2 giờ để gỡ lỗi một lớp con đã kiểm tra rỗng () trên một biến thành viên riêng của lớp cha của nó (phạm vi của biến thành viên của lớp cha NÊN đã được bảo vệ, nhưng trống () không trả về lỗi - kết quả chỉ đơn giản là một cái gì đó nên đã xảy ra, đã không xảy ra: sự không tồn tại của biến thành viên trong lớp con được xử lý giống hệt như khi biến thành viên này, một mảng, trống - tức là như thể nó không có phần tử). Đây là một vấn đề và một ví dụ khác về việc PHP quá dễ dãi.
Matthew Slyman

46

Tôi tò mò muốn biết cái nào thực sự nhanh hơn nên tôi đã tạo một tập lệnh đơn giản để đánh giá các chức năng đó.

<?php

function benchmark($name, $iterations, $action){
    $time=microtime(true);
    for($i=0;$i<=$iterations;++$i){
        $action();
    }
    echo $name . ' ' . round(microtime(true)-$time, 6) . "\n";
}

$iterations = 1000000;
$x = array();
$y = range(0, 10000000);
$actions = array(
    "Empty empty()" => function() use($x){
        empty($x);
    },
    "Empty count()" => function() use($x){
        count($x);
    },
    "Full empty()" => function() use($y){
        empty($y);
    },
    "Full count()" => function() use($y){
        count($y);
    },
    ############
    "IF empty empty()" => function() use($x){
        if(empty($x)){ $t=1; }
    },
    "IF empty count()" => function() use($x){
        if(count($x)){ $t=1; }
    },
    "IF full empty()" => function() use($y){
        if(empty($y)){ $t=1; }
    },
    "IF full count()" => function() use($y){
        if(count($y)){ $t=1; }
    },
    ############
    "OR empty empty()" => function() use($x){
        empty($x) OR $t=1;
    },
    "OR empty count()" => function() use($x){
        count($x) OR $t=1;
    },
    "OR full empty()" => function() use($y){
        empty($y) OR $t=1;
    },
    "OR full count()" => function() use($y){
        count($y) OR $t=1;
    },
    ############
    "IF/ELSE empty empty()" => function() use($x){
        if(empty($x)){ $t=1; } else { $t=2; }
    },
    "IF/ELSE empty count()" => function() use($x){
        if(count($x)){ $t=1; } else { $t=2; }
    },
    "IF/ELSE full empty()" => function() use($y){
        if(empty($y)){ $t=1; } else { $t=2; }
    },
    "IF/ELSE full count()" => function() use($y){
        if(count($y)){ $t=1; } else { $t=2; }
    },
    ############
    "( ? : ) empty empty()" => function() use($x){
        $t = (empty($x) ? 1 : 2);
    },
    "( ? : ) empty count()" => function() use($x){
        $t = (count($x) ? 1 : 2);
    },
    "( ? : ) full empty()" => function() use($y){
        $t = (empty($y) ? 1 : 2);
    },
    "( ? : ) full count()" => function() use($y){
        $t = (count($y) ? 1 : 2);
    }
);

foreach($actions as $name => $action){
    benchmark($name, $iterations, $action);
}
//END

Vì tôi đang làm điều đó, tôi cũng cố gắng kiểm tra hiệu suất thực hiện các hoạt động thường được liên kết với count () / blank ()

Sử dụng PHP 5.4.39:

Empty empty() 0.118691
Empty count() 0.218974
Full empty() 0.133747
Full count() 0.216424
IF empty empty() 0.166474
IF empty count() 0.235922
IF full empty() 0.120642
IF full count() 0.248273
OR empty empty() 0.123875
OR empty count() 0.258665
OR full empty() 0.157839
OR full count() 0.224869
IF/ELSE empty empty() 0.167004
IF/ELSE empty count() 0.263351
IF/ELSE full empty() 0.145794
IF/ELSE full count() 0.248425
( ? : ) empty empty() 0.169487
( ? : ) empty count() 0.265701
( ? : ) full empty() 0.149847
( ? : ) full count() 0.252891

Sử dụng HipHop VM 3.6.1 (dbg)

Empty empty() 0.210652
Empty count() 0.212123
Full empty() 0.206016
Full count() 0.204722
IF empty empty() 0.227852
IF empty count() 0.219821
IF full empty() 0.220823
IF full count() 0.221397
OR empty empty() 0.218813
OR empty count() 0.220105
OR full empty() 0.229118
OR full count() 0.221787
IF/ELSE empty empty() 0.221499
IF/ELSE empty count() 0.221274
IF/ELSE full empty() 0.221879
IF/ELSE full count() 0.228737
( ? : ) empty empty() 0.224143
( ? : ) empty count() 0.222459
( ? : ) full empty() 0.221606
( ? : ) full count() 0.231288

Kết luận nếu bạn đang sử dụng PHP:

  1. rỗng () nhanh hơn nhiều so với count () trong cả hai trường hợp, với một mảng trống và được điền

  2. count () thực hiện tương tự với một mảng đầy đủ hoặc rỗng.

  3. Thực hiện một IF đơn giản hoặc chỉ một phép toán Boolean đều giống nhau.

  4. IF / ELSE rất hiệu quả hơn một chút so với (?:). Trừ khi bạn đang thực hiện hàng tỷ lần lặp với các biểu thức ở giữa thì điều đó hoàn toàn không đáng kể.

Kết luận nếu bạn đang sử dụng HHVM:

  1. void () nhanh hơn count () một chút nhưng không đáng kể.

    [Phần còn lại giống như trong PHP]

Trong phần kết luận, nếu bạn chỉ cần biết mảng có rỗng hay không thì hãy sử dụng void ();

Đây chỉ là một thử nghiệm tò mò được thực hiện đơn giản mà không cần tính đến nhiều thứ. Nó chỉ là một bằng chứng về khái niệm và có thể không phản ánh các hoạt động trong sản xuất.


Cảm ơn vì mã thử nghiệm mẫu .... Tôi mới sử dụng nó và thấy rằng if($x){nó nhanh hơn if(empty($x)){(chỉ hoạt động nếu bạn biết rằng mã đó $xđã được khai báo).
Redzarf

Mã thử nghiệm của bạn thực sự rất tệ. Bạn thêm rất nhiều thứ bổ sung, chẳng hạn như lệnh gọi hàm ẩn danh. Nếu tôi loại bỏ và tôi chỉ chạy mã trần (cho chu kỳ sau nhau) thì tôi nhận được một sự khác biệt lớn. Và ý tôi là trong trường hợp đó càng nhanh nếu không có countemptycác lệnh gọi trong câu lệnh if. Sau đó, nó đến emptyvà kéo dài count. Nhưng so với của bạn trong trường hợp trần, trống nhanh hơn gấp mười lần! Kiểm tra mảng đơn giản: 0.104662, trống: 0.177659, đếm: 1.175125 trên PHP 5.6 nếu không mã của bạn cho kết quả tương tự trên phiên bản này giống như bạn đã đề cập. Chỉ là kết quả giả.
golddragon007

16

Tôi nghĩ đó chỉ là sở thích cá nhân. Một số người có thể nói emptylà nhanh hơn (ví dụ: http://jamessocol.com/projects/count_vs_empty.php ) trong khi những người khác có thể nói countlà tốt hơn vì ban đầu nó được tạo cho mảng. emptytổng quát hơn và có thể được áp dụng cho các loại khác.

php.net đưa ra cảnh báo sau cho countdù:

count () có thể trả về 0 cho một biến chưa được đặt, nhưng nó cũng có thể trả về 0 cho một biến đã được khởi tạo với một mảng trống. Sử dụng Isset () để kiểm tra xem một biến đã được đặt chưa.

Nói cách khác, nếu biến không được đặt, bạn sẽ nhận được thông báo từ PHP nói rằng nó không được xác định. Do đó, trước khi sử dụng count, bạn nên kiểm tra biến với isset. Điều này là không cần thiết với empty.


3
Thật thú vị khi một đối số ủng hộ countlà nó ban đầu được tạo ra cho các mảng ... nhưng các đối tượng có thể triển khai Countablevà bạn có thể chuyển các giá trị vô hướng đến count()và nhận được một kết quả hợp lệ.

1
đếm () có thể trở về 0 cho một biến mà không được thiết lập, nhưng nó có thể cũng ... . Tài liệu chính thức sử dụng động từ phương thức để bày tỏ sự không chắc chắn của nó: p
nawfal

Chỉ là một nhận xét về isset()điểm. Nếu bạn lo lắng về các thông báo trong PHP, bạn nên khai báo mảng của mình. Nếu bạn để PHP tự động khai báo mảng của mình, bạn cũng sẽ nhận được thông báo tại thời điểm đó. Tôi nghĩ rằng điểm thực sự của cảnh báo trên php.net là bạn không nên sử dụng countđể xác định xem một mảng đã được khai báo hay chưa vì nó mang lại kết quả giống như một mảng trống.
Noah Duncan

12

Có lý do gì mà số đếm nên được sử dụng thay vì số trống khi xác định xem một mảng có trống hay không?

Có, khi bạn cần làm điều gì đó trên mảng không trống khi biết kích thước của nó:

if( 0 < ( $cnt = count($array) ) )
{
 echo "Your array size is: $cnt";
}
else
 echo "Too bad, your array is empty :(";

Nhưng tôi không khuyên bạn nên sử dụng số đếm, trừ khi bạn chắc chắn 100% rằng những gì bạn đang đếm là một mảng. Gần đây, tôi đã gỡ lỗi mã, trong đó hàm lỗi trả về FALSEthay vì mảng trống và những gì tôi phát hiện ra là:

var_dump(count(FALSE));

đầu ra:

int 1

Vì vậy, kể từ đó tôi đang sử dụng emptyhoặc if(array() === $array)để chắc chắn rằng tôi có mảng trống.


6

count()dường như hoạt động tốt hơn với các giao diện dạng mảng có triển khai ArrayAccess/Countable. empty()trả về true cho các loại đối tượng này ngay cả khi chúng không có phần tử nào. Thông thường, các lớp này sẽ triển khai Countablegiao diện, vì vậy nếu câu hỏi là "Bộ sưu tập này có chứa các phần tử không?" mà không cần đưa ra giả định về việc thực hiện, thì đó count()là một lựa chọn tốt hơn.


Ý của bạn là " emptytrả về false cho những loại đối tượng này ngay cả khi chúng không có phần tử nào"?
alexw

Đúng. Không có giao diện nào để cho phép một lớp xác định xem nó có "rỗng" hay không. Và sẽ không thực sự có ý nghĩa nếu có một cái.
Ryan

+1 Việc sử dụng countsẽ là một giải pháp linh hoạt và có thể mở rộng hơn nếu mã của bạn chấp nhận một bộ sưu tập được triển khai theo cách "thông thường" là hợp lý… IMO có thể là tiêu chí thích hợp duy nhất để xác định xem bạn sử dụng counthay các cách khác ...
ClemC

Nhược điểm lớn count()của 7.2 là nó không còn có thể nhận các biến trống.
Ryan

5

Ngoài ra, bạn có thể ép kiểu biến dưới dạng boolean (ngầm định hoặc rõ ràng):

if( $value )
{
  // array is not empty
}

if( (bool) $value )
{
  // array is still not empty
}

Phương thức này tạo ra một E_NOTICEnếu biến không được xác định, tương tự như count().

Để biết thêm thông tin, hãy xem trang Hướng dẫn sử dụng PHP về so sánh kiểu .


1
Đây là cách tốt nhất để kiểm tra, chỉ sử dụng empty()nếu bạn đang cố gắng tránh kích hoạt một E_NOTICE (thường là một ý tưởng tồi, IMO). Sử dụng trống rỗng một cách rõ ràng sẽ dẫn đến mã lỗi.
Cobby

3

Sở thích cá nhân của tôi là viết mã sang trọng hơn (liên quan đến trường hợp sử dụng cụ thể của tôi). Tôi đồng ý với Dan McG bởi vì count () không phản hồi với kiểu dữ liệu chính xác (trong trường hợp này là boolean) cho bài kiểm tra được đề cập buộc nhà phát triển phải viết thêm mã để điền vào câu lệnh 'if'.

Liệu điều này có tác động đáng kể nào đến hiệu suất hay không chỉ còn là điều đáng bàn cãi đối với các mảng cực lớn (có thể bạn sẽ không có đủ phân bổ bộ nhớ trong hầu hết các thiết lập).

Đặc biệt khi nói đến mảng $ _POST của PHP, theo ý kiến ​​của tôi thì có vẻ "logic" hơn nhiều khi viết / xem:

if ( !empty ( $_POST ) ) {
    // deal with postdata
}

3

Hy vọng điều này có thể giúp ai đó mặc dù nó đã được trả lời (và tranh luận một số điều gì). Trong kịch bản của riêng tôi, tôi biết tất cả các mảng của tôi đều có 7 phần tử (kiểm tra đã được thực hiện trước đó trong mã của tôi) và tôi đang thực hiệnarray_diff điều tất nhiên trả về mảng 0 khi bằng nhau.

Tôi đã có 34 giây cho countvà 17 giây cho empty. Cả hai đều cung cấp cho tôi các phép tính giống nhau nên mã của tôi vẫn ổn.

Tuy nhiên, bạn cũng có thể thử ==hoặc ===như trong PHP - Kiểm tra xem hai mảng có bằng nhau không . Tốt nhất tôi nên nói là thử countvs emptyvs == empty array, sau đó xem cái nào mang lại đặc điểm tốt nhất của riêng bạn. Trong trường hợp của tôi countlà chậm nhất nên tôi đang sử dụng emptybây giờ ... sẽ kiểm tra serializetiếp theo


2

Không có lý do mạnh mẽ để thích count($myArray) == 0hơn empty($myArray). Chúng có ngữ nghĩa giống hệt nhau. Một số có thể thấy cái này dễ đọc hơn cái khác. Một cái có thể hoạt động tốt hơn một chút so với cái kia nhưng nó không có khả năng là một yếu tố quan trọng trong đại đa số các ứng dụng php. Đối với tất cả các mục đích thực tế, sự lựa chọn là một vấn đề của thị hiếu.


1
Còn điều "biểu diễn"? Sử dụng giải thích về "mục đích thực hành" dẫn đến thói quen xấu. Sử dụng countkhi bạn cần đếm, sử dụng emptykhi bạn cần kiểm tra xem bộ sưu tập có trống không. Tất nhiên có những trường hợp cạnh như chuỗi hoặc null, nhưng lập trình viên cần suy nghĩ về mã của mình. Bạn có thể không đồng ý, bạn được phép.
Namek

đôi khi, với số đếm ($ myArray) nếu $ myArray là booleen giống như một giá trị FALSE, thì số đếm không hoạt động (được thử nghiệm trên php5.3).
Mimouni

1

Đôi khi sử dụng trống là điều bắt buộc. Ví dụ mã này:

$myarray = array();

echo "myarray:"; var_dump($myarray); echo "<br>";
echo "case1 count: ".count($myarray)."<br>";
echo "case1 empty: ".empty($myarray)."<br>";

$glob = glob('sdfsdfdsf.txt');

echo "glob:"; var_dump($glob); echo "<br>";
echo "case2 count: ".count($glob)."<br>";
echo "case2 empty: ".empty($glob);

Nếu bạn chạy mã này như thế này: http://phpfiddle.org/main/code/g9x-uwi

Bạn nhận được kết quả này:

myarray:array(0) { } 
case1 count: 0
case1 empty: 1

glob:bool(false) 
case2 count: 1
case2 empty: 1

Vì vậy, nếu bạn count đầu ra hình cầu trống, bạn sẽ nhận được đầu ra sai. Bạn nên kiểm tra sự trống rỗng.

Từ tài liệu toàn cầu :

Trả về một mảng chứa các tệp / thư mục phù hợp, một mảng trống nếu không có tệp nào khớp hoặc FALSE do lỗi.
Lưu ý: Trên một số hệ thống, không thể phân biệt giữa kết quả trống và lỗi.

Cũng kiểm tra câu hỏi này: Tại sao đếm (sai) trả về 1?


1

Kể từ khi một biến phân tích cú pháp như tiêu cực sẽ trở lại int(1)vớicount()

Tôi thích ($array === [] || !$array)kiểm tra một mảng trống.

Đúng, chúng ta nên mong đợi một mảng trống, nhưng chúng ta không nên mong đợi một triển khai tốt trên các hàm mà không có kiểu trả về được thực thi.

Ví dụ với count()

var_dump(count(0));
> int(1)
var_dump(count(false));
> int(1)

0

Tôi làm lại tâm trí của tôi guys, cảm ơn.

Ok, không có sự khác biệt giữa việc sử dụng emptycount. Về mặt kỹ thuật, countnên được sử dụng cho mảng và emptycó thể được sử dụng cho mảng cũng như chuỗi. Vì vậy, trong hầu hết các trường hợp, chúng có thể hoán đổi cho nhau và nếu bạn xem tài liệu php, bạn sẽ thấy danh sách gợi ý countnếu bạn đang ở emptyvà ngược lại.

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.