it-swarm.com.ru

Проверка наличия пустых массивов: считать против пустых

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

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

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

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

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

88
Dan McGrath

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

87
prodigitalson

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

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

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

39
Satake

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

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

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

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

15
Laurent le Beau-Martin

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

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

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

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

var_dump(count(FALSE));

Результат:

int 1

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

10
dev-null-dweller

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

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

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

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

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

5
user212218

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

5
Ryan

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

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

В частности, когда речь идет о массиве PHP $ _POST, на мой взгляд, гораздо более «логично» писать/видеть:

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

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

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

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

3
xchiltonx

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

$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, вы получите неправильный вывод. Вы должны проверить на пустоту.

От глобус документация:

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

Также проверьте этот вопрос: Почему count (false) возвращает 1?

1
trante

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

1
Asaph

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

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

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

Примеры с count()

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

Я переделал свой разум, ребята, спасибо.

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

0
Sarfraz