如何使用PHP检查数组是否为空?

611

players 可能是空的或者是一个逗号分隔的列表(或单个值)。如何最简单地检查它是否为空?我假设我可以在将 $gameresult 数组提取到 $gamerow 后立即这样做。在这种情况下,如果它是空的,跳过分解 $playerlist 可能更有效率,但是为了论证,如果要检查一个数组是否为空,应该怎么办?

$gamerow = mysql_fetch_array($gameresult);
$playerlist = explode(",", $gamerow['players']);
24个回答

995

如果你只需要检查数组中是否有任何元素,你可以使用数组本身(由于PHP的松散类型)或者-如果你更喜欢严格的方法-使用count()

if (!$playerlist) {
     // list is empty.
}
if (count($playerlist) === 0) {
     // list is empty.
}

如果你需要在检查之前清除空值(通常这样做是为了防止对奇怪的字符串使用explode函数):

foreach ($playerlist as $key => $value) {
    if (!strlen($value)) {
       unset($playerlist[$key]);
    }
}
if (!$playerlist) {
   //empty array
}

4
不应该使用 count,而应该使用 empty。对于大型数组,使用 count 执行时间更长。 - Dan McGrath
5
根据他的代码示例,变量将被设置,因此您不需要使用 empty() - Cobby
8
注意!if(!isset($emptyarray))的值为false,但是if(empty($emptyarray))的值为true。这正是让我掉进坑里的地方。 - Kellen Stuart
2
@Kolob Canyon.. 你期望什么?(假设你实际上定义了一个数组...)。对我来说,某些东西可以被“设置”并且是“空的”是有意义的。 - McAuley
2
@DanMcG count()是一个存储值(O(1))...请注意,数组的大小与性能无关:https://dev59.com/uG455IYBdhLWcg3wD_sB和https://dev59.com/c2025IYBdhLWcg3wtofX。`count()`和`!empty()`都是对已声明数组不必要的调用。https://dev59.com/fXE95IYBdhLWcg3wp_qn#59958121 - mickmackusa
显示剩余3条评论

204

在PHP中,一个空数组是假值(falsey),所以你甚至不需要像其他人建议的那样使用empty()

<?php
$playerList = array();
if (!$playerList) {
    echo "No players";
} else {
    echo "Explode stuff...";
}
// Output is: No players

empty() 是 PHP 中的一个函数,用于检查变量是否不存在或其值为假(如array(), 0, null, false等)。

大多数情况下您只需使用!$emptyVar进行检查。如果变量可能未被设置且您不想触发E_NOTICE,则可以使用empty($emptyVar)进行检查;但在我看来这通常是不好的做法。


4
希望这不会在某个标准中改变...那会很痛苦。 - David Constantine

101

有些不错的答案,但我想扩展一下,更清楚地解释PHP何时确定一个数组为空。


主要注意事项:

具有键(或键)的数组将被PHP确定为非空

由于数组值需要键才能存在,因此在数组中具有值与否并不决定它是否为空,只有没有键(因此没有值)时才为空。

因此,使用empty()检查数组不仅告诉您是否具有值,而且还告诉您数组是否为空,并且键是数组的一部分。


因此,在决定使用哪种检查方法之前,请考虑如何生成数组。
例如,当用户提交HTML表单时,每个表单字段都有一个数组名称(即name="array[]"),则数组具有键。
对于每个表单字段的数组,都会生成非空数组,因为每个表单字段的数组将具有自动递增的键值。

以这些数组为例:

/* Assigning some arrays */

// Array with user defined key and value
$ArrayOne = array("UserKeyA" => "UserValueA", "UserKeyB" => "UserValueB");

// Array with auto increment key and user defined value
// as a form field would return with user input
$ArrayTwo[] = "UserValue01";
$ArrayTwo[] = "UserValue02";

// Array with auto incremented key and no value
// as a form field would return without user input
$ArrayThree[] = '';
$ArrayThree[] = '';

如果你输出上述数组的键和值,你将得到以下结果:

数组一:
[UserKeyA] => [UserValueA]
[UserKeyB] => [UserValueB]

数组二:
[0] => [UserValue01]
[1] => [UserValue02]

数组三:
[0] => []
[1] => []

而使用empty()测试上述数组将返回以下结果:

数组一:
$ArrayOne 不为空

数组二:
$ArrayTwo 不为空

数组三:
$ArrayThree 不为空

当你声明一个数组但之后没有使用它时,该数组将始终为空,例如:

$ArrayFour = array();
这将是空的,即在上面使用 empty() 时,PHP 将返回 TRUE。
因此,如果您的数组具有键 - 可通过表单输入名称或手动分配它们(例如创建一个仅具有数据库列名作为键但没有来自数据库的值/数据的数组)来实现,则该数组将不会是 empty()
在这种情况下,您可以在 foreach 中循环数组,测试每个键是否具有值。如果您需要遍历数组并检查键或净化数据,则这是一种很好的方法。
但是,如果您只需要知道“是否存在值”返回TRUEFALSE,则这不是最佳方法。当已知数组将具有键时,有各种方法来确定数组是否具有任何值。函数或类可能是最好的方法,但始终取决于您的环境和确切要求,以及其他事项,例如您当前对数组执行的操作(如果有)。
以下是使用非常少的代码检查数组是否具有值的方法:
使用 array_filter()
迭代数组中的每个值,将其传递给回调函数。如果回调函数返回 true,则从数组返回当前值到结果数组。数组键保留。
$EmptyTestArray = array_filter($ArrayOne);

if (!empty($EmptyTestArray))
  {
    // do some tests on the values in $ArrayOne
  }
else
  {
    // Likely not to need an else, 
    // but could return message to user "you entered nothing" etc etc
  }

对三个示例数组(在此答案的第一个代码块中创建)运行array_filter()的结果如下:

数组一:
$arrayone不为空

数组二:
$arraytwo不为空

数组三:
$arraythree为空

因此,当没有值时,无论是否有键,使用array_filter()创建一个新数组,然后检查新数组是否为空,即可显示原始数组中是否有任何值。
虽然不是最理想的,有点混乱,但如果您有一个巨大的数组并且不需要为任何其他原因循环遍历它,则这是所需代码最简单的方法。


我没有检查过开销,但是了解使用array_filter()和使用foreach检查是否找到值之间的区别会很有好处。

显然,基准测试需要在各种参数、小型和大型数组以及有值和没有值的情况下进行。


3
非常感谢。这真的很有帮助,而且使用array_filter()解决了我的问题。 - Brian Powell
empty(array()) 总是会被计算为 FALSE,因此添加 count(array())==0 将产生 true。 - timmz
2
@mboullouz count(array())==0 当数组有键但没有值时是错误的,因此这不能帮助我们仅检查值。您的陈述是正确的,但是您正在强制使用count(array())进行测试,因为数组当然是空的。我们需要检查数组是否从表单或其他地方返回以知道它是否为空(键/值)或只是有值或没有。 - James
1
这个解决方案非常适用于这种类型的数组,例如当您想验证输入文件时会很有帮助。array_filter($_FILES["documento"]['name']) - Gendrith

24

2
老派永远是最好的,只需检查数组的索引即可。 - Danish
@Danish 这里描述的方法是使用if (count($arr) === 0) { /* the array is empty */},而不是检查数组的索引。$gamerow['players']与测试是否为空无关,那只是OP提供的一些不相关的样板代码。 - ggorlen

21

我运行了帖子末尾附带的基准测试。 为了比较这些方法:

  • count($arr) == 0 :使用 count 函数
  • empty($arr) :使用 empty 函数
  • $arr == [] :进行比较操作
  • (bool) $arr :强制转换类型

然后得到了以下结果。

Contents  \method |    count     |    empty     |     comp     |     cast     |
------------------|--------------|--------------|--------------|--------------|
            Empty |/* 1.213138 */|/* 1.070011 */|/* 1.628529 */|   1.051795   |
          Uniform |/* 1.206680 */|   1.047339   |/* 1.498836 */|/* 1.052737 */|
          Integer |/* 1.209668 */|/* 1.079858 */|/* 1.486134 */|   1.051138   |
           String |/* 1.242137 */|   1.049148   |/* 1.630259 */|/* 1.056610 */|
            Mixed |/* 1.229072 */|/* 1.068569 */|/* 1.473339 */|   1.064111   |
      Associative |/* 1.206311 */|   1.053642   |/* 1.480637 */|/* 1.137740 */|
------------------|--------------|--------------|--------------|--------------|
            Total |/* 7.307005 */|   6.368568   |/* 9.197733 */|/* 6.414131 */|

使用空值和强制转换为布尔类型之间的区别微不足道。我运行过这个测试多次,它们似乎基本上是等价的。数组的内容似乎不起显着作用。两者产生相反的结果,但逻辑否定几乎足以使强制转换大部分时间胜出,因此我个人更喜欢在任何情况下都使用empty来提高可读性。

#!/usr/bin/php
<?php

//    012345678
$nt = 90000000;

$arr0 = [];
$arr1 = [];
$arr2 = [];
$arr3 = [];
$arr4 = [];
$arr5 = [];

for ($i = 0; $i < 500000; $i++) {
    $arr1[] = 0;
    $arr2[] = $i;
    $arr3[] = md5($i);
    $arr4[] = $i % 2 ? $i : md5($i);
    $arr5[md5($i)] = $i;
}

$t00 = microtime(true);
for ($i = 0; $i < $nt; $i++) {
    count($arr0) == 0;
}
$t01 = microtime(true);
for ($i = 0; $i < $nt; $i++) {
    empty($arr0);
}
$t02 = microtime(true);
for ($i = 0; $i < $nt; $i++) {
    $arr0 == [];
}
$t03 = microtime(true);
for ($i = 0; $i < $nt; $i++) {
    (bool) $arr0;
}
$t04 = microtime(true);

$t10 = microtime(true);
for ($i = 0; $i < $nt; $i++) {
    count($arr1) == 0;
}
$t11 = microtime(true);
for ($i = 0; $i < $nt; $i++) {
    empty($arr1);
}
$t12 = microtime(true);
for ($i = 0; $i < $nt; $i++) {
    $arr1 == [];
}
$t13 = microtime(true);
for ($i = 0; $i < $nt; $i++) {
    (bool) $arr1;
}
$t14 = microtime(true);

/* ------------------------------ */

$t20 = microtime(true);
for ($i = 0; $i < $nt; $i++) {
    count($arr2) == 0;
}
$t21 = microtime(true);
for ($i = 0; $i < $nt; $i++) {
    empty($arr2);
}
$t22 = microtime(true);
for ($i = 0; $i < $nt; $i++) {
    $arr2 == [];
}
$t23 = microtime(true);
for ($i = 0; $i < $nt; $i++) {
    (bool) $arr2;
}
$t24 = microtime(true);

/* ------------------------------ */

$t30 = microtime(true);
for ($i = 0; $i < $nt; $i++) {
    count($arr3) == 0;
}
$t31 = microtime(true);
for ($i = 0; $i < $nt; $i++) {
    empty($arr3);
}
$t32 = microtime(true);
for ($i = 0; $i < $nt; $i++) {
    $arr3 == [];
}
$t33 = microtime(true);
for ($i = 0; $i < $nt; $i++) {
    (bool) $arr3;
}
$t34 = microtime(true);

/* ------------------------------ */

$t40 = microtime(true);
for ($i = 0; $i < $nt; $i++) {
    count($arr4) == 0;
}
$t41 = microtime(true);
for ($i = 0; $i < $nt; $i++) {
    empty($arr4);
}
$t42 = microtime(true);
for ($i = 0; $i < $nt; $i++) {
    $arr4 == [];
}
$t43 = microtime(true);
for ($i = 0; $i < $nt; $i++) {
    (bool) $arr4;
}
$t44 = microtime(true);

/* ----------------------------------- */

$t50 = microtime(true);
for ($i = 0; $i < $nt; $i++) {
    count($arr5) == 0;
}
$t51 = microtime(true);
for ($i = 0; $i < $nt; $i++) {
    empty($arr5);
}
$t52 = microtime(true);
for ($i = 0; $i < $nt; $i++) {
    $arr5 == [];
}
$t53 = microtime(true);
for ($i = 0; $i < $nt; $i++) {
    (bool) $arr5;
}
$t54 = microtime(true);

/* ----------------------------------- */

$t60 = $t00 + $t10 + $t20 + $t30 + $t40 + $t50;
$t61 = $t01 + $t11 + $t21 + $t31 + $t41 + $t51;
$t62 = $t02 + $t12 + $t22 + $t32 + $t42 + $t52;
$t63 = $t03 + $t13 + $t23 + $t33 + $t43 + $t53;
$t64 = $t04 + $t14 + $t24 + $t34 + $t44 + $t54;

/* ----------------------------------- */

$ts0[1] = number_format(round($t01 - $t00, 6), 6);
$ts0[2] = number_format(round($t02 - $t01, 6), 6);
$ts0[3] = number_format(round($t03 - $t02, 6), 6);
$ts0[4] = number_format(round($t04 - $t03, 6), 6);

$min_idx = array_keys($ts0, min($ts0))[0];
foreach ($ts0 as $idx => $val) {
    if ($idx == $min_idx) {
        $ts0[$idx] = "   $val   ";
    } else {
        $ts0[$idx] = "/* $val */";
    }

}

$ts1[1] = number_format(round($t11 - $t10, 6), 6);
$ts1[2] = number_format(round($t12 - $t11, 6), 6);
$ts1[3] = number_format(round($t13 - $t12, 6), 6);
$ts1[4] = number_format(round($t14 - $t13, 6), 6);

$min_idx = array_keys($ts1, min($ts1))[0];
foreach ($ts1 as $idx => $val) {
    if ($idx == $min_idx) {
        $ts1[$idx] = "   $val   ";
    } else {
        $ts1[$idx] = "/* $val */";
    }

}

$ts2[1] = number_format(round($t21 - $t20, 6), 6);
$ts2[2] = number_format(round($t22 - $t21, 6), 6);
$ts2[3] = number_format(round($t23 - $t22, 6), 6);
$ts2[4] = number_format(round($t24 - $t23, 6), 6);

$min_idx = array_keys($ts2, min($ts2))[0];
foreach ($ts2 as $idx => $val) {
    if ($idx == $min_idx) {
        $ts2[$idx] = "   $val   ";
    } else {
        $ts2[$idx] = "/* $val */";
    }

}

$ts3[1] = number_format(round($t31 - $t30, 6), 6);
$ts3[2] = number_format(round($t32 - $t31, 6), 6);
$ts3[3] = number_format(round($t33 - $t32, 6), 6);
$ts3[4] = number_format(round($t34 - $t33, 6), 6);

$min_idx = array_keys($ts3, min($ts3))[0];
foreach ($ts3 as $idx => $val) {
    if ($idx == $min_idx) {
        $ts3[$idx] = "   $val   ";
    } else {
        $ts3[$idx] = "/* $val */";
    }

}

$ts4[1] = number_format(round($t41 - $t40, 6), 6);
$ts4[2] = number_format(round($t42 - $t41, 6), 6);
$ts4[3] = number_format(round($t43 - $t42, 6), 6);
$ts4[4] = number_format(round($t44 - $t43, 6), 6);

$min_idx = array_keys($ts4, min($ts4))[0];
foreach ($ts4 as $idx => $val) {
    if ($idx == $min_idx) {
        $ts4[$idx] = "   $val   ";
    } else {
        $ts4[$idx] = "/* $val */";
    }

}

$ts5[1] = number_format(round($t51 - $t50, 6), 6);
$ts5[2] = number_format(round($t52 - $t51, 6), 6);
$ts5[3] = number_format(round($t53 - $t52, 6), 6);
$ts5[4] = number_format(round($t54 - $t53, 6), 6);

$min_idx = array_keys($ts5, min($ts5))[0];
foreach ($ts5 as $idx => $val) {
    if ($idx == $min_idx) {
        $ts5[$idx] = "   $val   ";
    } else {
        $ts5[$idx] = "/* $val */";
    }

}

$ts6[1] = number_format(round($t61 - $t60, 6), 6);
$ts6[2] = number_format(round($t62 - $t61, 6), 6);
$ts6[3] = number_format(round($t63 - $t62, 6), 6);
$ts6[4] = number_format(round($t64 - $t63, 6), 6);

$min_idx = array_keys($ts6, min($ts6))[0];
foreach ($ts6 as $idx => $val) {
    if ($idx == $min_idx) {
        $ts6[$idx] = "   $val   ";
    } else {
        $ts6[$idx] = "/* $val */";
    }

}

echo "             |    count     |    empty     |     comp     |     cast     |\n";
echo "-------------|--------------|--------------|--------------|--------------|\n";
echo "       Empty |";
echo $ts0[1] . '|';
echo $ts0[2] . '|';
echo $ts0[3] . '|';
echo $ts0[4] . "|\n";

echo "     Uniform |";
echo $ts1[1] . '|';
echo $ts1[2] . '|';
echo $ts1[3] . '|';
echo $ts1[4] . "|\n";

echo "     Integer |";
echo $ts2[1] . '|';
echo $ts2[2] . '|';
echo $ts2[3] . '|';
echo $ts2[4] . "|\n";

echo "      String |";
echo $ts3[1] . '|';
echo $ts3[2] . '|';
echo $ts3[3] . '|';
echo $ts3[4] . "|\n";

echo "       Mixed |";
echo $ts4[1] . '|';
echo $ts4[2] . '|';
echo $ts4[3] . '|';
echo $ts4[4] . "|\n";

echo " Associative |";
echo $ts5[1] . '|';
echo $ts5[2] . '|';
echo $ts5[3] . '|';
echo $ts5[4] . "|\n";

echo "-------------|--------------|--------------|--------------|--------------|\n";
echo "       Total |";
echo $ts6[1] . '|';
echo $ts6[2] . '|';
echo $ts6[3] . '|';
echo $ts6[4] . "|\n";

很好的基准测试,但你忘记了 sizeof,它不是 empty 的别名... https://dev59.com/2Yjca4cB1Zd3GeqPvVnC#51986794 - Yousha Aleayoub
FYI:当我使用 PHP 7.4 运行此基准测试时,我得到了不同的结果,表明比较是最快的。 - Nick Merrill
3
你应该使用===而不是== - Minding

20

如果您想排除假的或空的行(例如0 => ''),而使用empty()将失败,您可以尝试:

if (array_filter($playerlist) == []) {
  // Array is empty!
}

array_filter()函数:如果没有提供回调函数,那么所有等于FALSE(参见转换为布尔型)的数组条目都将被移除。

如果您想要移除所有的NULL、FALSE和空字符串(''),但保留零值(0),可以使用strlen作为回调函数,例如:

$is_empty = array_filter($playerlist, 'strlen') == [];

1
这是对不同问题的正确答案。使用数组过滤器将破坏具有falsey值的现有元素。这不是OP所要求的。 - mickmackusa
这是误导性的,与问题完全无关。 - ggorlen

14

如果您想确定正在测试的变量是否实际上是显式的空数组,可以使用类似以下代码:

if ($variableToTest === array()) {
    echo 'this is explicitly an empty array!';
}

这个方法虽然可行,但你在分配一个空数组,却立即将其扔进垃圾回收站。而且其他答案中已经多次提到了这一点。 - ggorlen

7
为什么没有人提出这个答案:
$array = [];

if($array == []) {
    // array is empty
}

2
你的说法不正确。一年前,Tim Ogilvy 已经给出了这个答案。使用方括号 [] 代替 array() 是相同的。 - mickmackusa
虽然在底层它是相同的答案...从技术上讲。我使用了方括号而不是过时的数组函数。 - Rob
3
如果你使用这种方法,应该使用===代替==,因为它更快。 - Minding
1
@Minding:不仅因为它更快,而且因为它更正确。 - cherouvim
如果你使用这个答案,那么无论你如何比较数组,你都不在乎速度。 "==="或"=="的可能微不足道的开销应该远远小于"[]"的对象分配和垃圾回收的成本。请参见线程中的基准测试。 - ggorlen

7

如果你想检查数组内容,可以使用以下方法:

$arr = array();

if(!empty($arr)){
  echo "not empty";
}
else 
{
  echo "empty";
}

see here: http://codepad.org/EORE4k7v


正如Cobby在2012年所示,调用函数来检查已声明的数组是否为空是不必要的。 - mickmackusa
@mickmackusa 我在这里不同意你的看法。按照这个逻辑,我们可以解散 empty(),因为 empty 检查变量是否设置以及值是否为 falsey。有些人宁愿为可读性创建(几乎不可见的)开销。 - I try so hard but I cry harder
如果您喜欢声明式编码风格,请使用 empty()。我的观点是这并非必要。 - mickmackusa

7
is_array($detect) && empty($detect);

is_array


这些都是不必要的检查。OP正在调用explode()--它返回数组类型数据。检查empty()是一个多余的函数调用。正如Cobby在2012年所述, if($detect)就足够了。这个解决方案不应该被用于此任务或其他任务。你可能会争辩说你在覆盖这个问题范围之外的情况,但是从来没有必要在is_array()之后调用empty(),因为如果变量没有“设置”,那么is_array()会生成“Notice: Undefined variable”,如果isset(),那么empty()是过度的,只需使用Cobby的答案即可。 - mickmackusa
1
@mickmackusa 如果变量被设置为空数组怎么办?也许你想要检查你将要评估的数据是否是一个数组,然后再检查它是否为空。 - I try so hard but I cry harder
如果您想检查一个已声明的变量是否为数组且非空,则只需要这样做:if (is_array($detect) && $detect)。如果您想强制将变量转换为数组,则可以将其强制转换为数组(这将保留数组不变,将对象的第一级转换为数组,并将任何标量值转换为包含该值的单元素数组)$detect = (array)$detect; if ($detect) - mickmackusa
相当于 $detect === [],请参见 Tim 上面的回答 - kiatng
@kiatng 这两者并不等价。这个答案没有分配内存,而 $detect === [] 则有。 - ggorlen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接