Проверка пустых массивов: count vs empty

Этот вопрос о том, « Как определить, пуст PHP пуст », заставил меня подумать об этом вопросе

Есть ли причина, по которой count следует использовать вместо empty при определении, является ли массив пустым или нет?

Моя личная мысль была бы, если 2 эквивалентны для пустых массивов, которые вы должны использовать empty потому что он дает логический ответ на логический вопрос. Из связанного выше вопроса кажется, что count($var) == 0 является популярным методом. Для меня, в то время как технически правильно, не имеет никакого смысла. Например, Q: $ var, вы пусты? A: 7 . Хммм …

Есть ли причина, по которой я должен использовать count == 0 или просто вопрос личного вкуса?

Как было указано другими в комментариях к удаленному ответу, count будет иметь влияние производительности для больших массивов, потому что ему придется подсчитывать все элементы, тогда как empty может остановиться, как только он узнает, что он не пуст. Итак, если они дают одинаковые результаты в этом случае, но count потенциально неэффективен, почему мы когда-либо использовали count($var) == 0 ?

    Обычно я использую empty . Я не уверен, почему люди будут использовать счет действительно. Если массив большой, то счет занимает больше времени / имеет больше накладных расходов. Если вам просто нужно знать, пуст ли массив, то используйте пустой.

    Мне было интересно узнать, какой из них был быстрее, поэтому я сделал простой сценарий для сравнения этих функций.

     <?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 

    Поскольку я делал это, я также пытался проверить эффективность выполнения операций, которые обычно связывались с count () / empty ()

    Использование 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 

    Использование 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 

    Выводы, если вы используете PHP:

    1. empty () намного быстрее, чем count () в обоих сценариях, с пустым и заполненным массивом

    2. count () выполняет то же самое с полным или пустым массивом.

    3. Выполнение простого IF или просто логическая операция – то же самое.

    4. IF / ELSE очень немного эффективнее, чем (?:). Если вы не делаете миллиарды итераций с выражениями в середине, это совершенно незначительно.

    Выводы, если вы используете HHVM:

    1. empty () является младшим битком быстрее, чем count (), но незначительно.

      [Остальное такое же, как в PHP]

    В заключение, если вам просто нужно знать, пусто ли массив, всегда используйте empty ();

    Это было просто любопытное испытание, просто сделанное без учета многих вещей. Это просто доказательство концепции и может не отражать операции в производстве.

    Я думаю, что это только личные предпочтения. Некоторые люди могут сказать, что empty быстрее (например, http://jamessocol.com/projects/count_vs_empty.php ), в то время как другие могут сказать, что count лучше, поскольку он был первоначально создан для массивов. empty является более общим и может применяться к другим типам.

    php.net дает следующее предупреждение для count :

    count () может возвращать 0 для переменной, которая не задана, но она также может возвращать 0 для переменной, которая была инициализирована пустым массивом. Используйте isset (), чтобы проверить, установлена ​​ли переменная.

    Другими словами, если переменная не задана, вы получите уведомление от PHP о том, что она не определена. Поэтому, прежде чем использовать count , было бы лучше проверить переменную с isset . Это не обязательно с empty .

    Есть ли причина, по которой счетчик следует использовать вместо пустого при определении, является ли массив пустым или нет?

    Существует, когда вам нужно что-то делать на непустом массиве, зная, что это размер:

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

    Но я бы не рекомендовал использовать счетчик, если вы не уверены на 100%, что вы считаете массив. В последнее время я отлаживал код, где функция error возвращала FALSE вместо пустого массива, и я обнаружил:

     var_dump(count(FALSE)); 

    вывод:

     int 1 

    Поэтому с тех пор я использую empty или if(array() === $array) чтобы убедиться, что у меня есть пустой массив .

    ArrayAccess/Countable что ArrayAccess/Countable count() работает лучше с ArrayAccess/Countable интерфейсами, которые реализуют ArrayAccess/Countable . empty() возвращает true для этих объектов, даже если у них нет элементов. Как правило, эти классы будут реализовывать интерфейс Countable , поэтому, если возникает вопрос: содержит ли эта коллекция элементы? не делая предположения о реализации, то count() является лучшим вариантом.

    В качестве альтернативы вы можете использовать переменную как логическую (неявно или явно):

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

    Этот метод генерирует E_NOTICE если переменная не определена, аналогично count() .

    Для получения дополнительной информации см. Страницу руководства PHP по сопоставлениям типов .

    Мои личные предпочтения в большей степени связаны с элегантностью кодирования (по отношению к моему конкретному случаю использования). Я согласен с Дэном Макгем, поскольку count () не отвечает правильным типом данных (в данном случае логическим) для рассматриваемого теста, заставляя разработчика писать больше кода для заполнения оператора if.

    Независимо от того, оказывает ли это какое-либо существенное влияние на производительность, только дискуссионно для чрезвычайно больших массивов (у вас, вероятно, не будет достаточного распределения памяти в любом случае в большинстве настроек).

    В частности, когда дело доходит до массива $ _POST PHP, кажется, что, по-моему, гораздо логичнее писать / видеть:

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

    Надеюсь, что это может помочь кому-то, хотя на это уже был дан ответ (и обсуждался какой-то). В моем собственном сценарии я знаю, что все мои массивы имеют 7 элементов (проверки были сделаны ранее в моем коде), и я выполняю array_diff который, естественно, возвращает массив равным нулю.

    У меня было 34 секунды для count и 17 секунд для empty . Оба дают мне те же вычисления, поэтому мой код по-прежнему прекрасен.

    Однако вы также можете попробовать == или === как в PHP. Проверьте, равны ли два массива . Лучшее, что я сказал бы, это попробовать count против empty vs == empty array , а затем посмотреть, какие из них дают ваши лучшие лучшие функции. В моем случае count было самым медленным, поэтому я использую empty сейчас … будет проверять serialize следующей

    Нет никакой веской причины предпочитать count($myArray) == 0 над empty($myArray) . Они имеют идентичную семантику. Некоторые могут найти еще один читаемый, чем другой. Можно сделать немного лучше, чем другие, но вряд ли это будет значительным фактором в подавляющем большинстве приложений php. Для всех практических целей выбор – это вопрос вкуса.

    Иногда использование пустого является обязательным. Например, этот код:

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

    Если вы запустите этот код следующим образом: http://phpfiddle.org/main/code/g9x-uwi

    Вы получаете этот результат:

     myarray:array(0) { } case1 count: 0 case1 empty: 1 glob:bool(false) case2 count: 1 case2 empty: 1 

    Поэтому, если вы count пустой выход glob, вы получите неправильный вывод. Вы должны проверить пустоту.

    Из документации glob :

    Возвращает массив, содержащий совпадающие файлы / каталоги, пустой массив, если файл не соответствует или FALSE при ошибке.
    Примечание. В некоторых системах невозможно различить пустое совпадение и ошибку.

    Также проверьте этот вопрос: зачем считать (false) return 1?

    Спасибо, ребята.

    Хорошо, нет никакой разницы между использованием empty и count . Технически count должен использоваться для массивов, а empty может использоваться как для массивов, так и для строк. Поэтому в большинстве случаев они взаимозаменяемы, и если вы видите документы php, вы увидите список предложений, если вы на empty и наоборот.

    Поскольку переменная, обработанная как отрицательная, возвращает int(1) с count()

    Я предпочитаю ($array === [] || !$array) тестировать пустой массив.

    Да, мы должны ожидать пустой массив, но мы не должны ожидать хорошей реализации функций без принудительных типов возвращаемых данных.

    Примеры с count()

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