Php中的in_array函数如何判断0值?

34

我试图理解下面这种情况下的in_array行为:

$arr = array(2 => 'Bye', 52, 77, 3 => 'Hey');
var_dump(in_array(0, $arr));
in_array() 函数的返回值是布尔型的 true。正如你所看到的,没有任何值等于 0,所以如果有人能帮我理解为什么这个函数返回 true,那就太好了。

2
我在这个数组中看到两个值相等为0的条目。 - dev-null-dweller
嘿,乔纳森,谢谢你的回答,真的很好,再次感谢并祝你有美好的一天。 - Aviel Fedida
5个回答

70

根据文档中的评论,这是一个已知问题。请看以下示例:

in_array(0, array(42));      // FALSE
in_array(0, array('42'));    // FALSE
in_array(0, array('Foo'));   // TRUE
为了避免这种情况,提供第三个参数true,将比较放在严格模式下,这将不仅比较值,还会比较类型。
var_dump(in_array(0, $arr, true));

还有其他方法可以解决问题,无需将每个检查都放在严格模式下:

in_array($value, $my_array, empty($value) && $value !== '0');

为什么会这样?

所有这一切背后的原因很可能是字符串转数字的转换。如果我们试图从“Bye”中获取一个数字,我们将得到 0,这也是我们想要查找的值。

echo intval("Bye"); // 0

为了确认这一点,我们可以使用array_search函数来查找与匹配值相关联的键:

$arr = array(2 => 'Bye', 52, 77, 3 => 'Hey');
echo array_search(0, $arr);

在这个例子中,返回的键值是2,表示在将Bye转换为整数时找到了0


3
如果解释一下为什么 PHP 认为 0 == 'string' 为 TRUE,这个回答会更好。 - ernie
是的,我也不确定为什么……我在我的答案中发布了我的实验/结论,以及关于字符串被转换为0的具体行,但还是谢谢你的澄清。 - ernie
@ernie 做得好。我想自然的做法是利用 array_search 来查看 PHP 找到与 0 相等的值,果然它是第一个不以数字开头的字符串。 - Sampson
绝对是一个有趣的小问题 - 没想到字符串在类型转换期间通常会被转换为0,并且宽松的字符串/数字比较将默认为数值比较。 - ernie
2
@ernie 一个字符串'4u'在操作后会被转换为数字4。但如果第一个字符不是数字,则会转换为0。绝对是一个有趣的问题。 - Sampson

10

尝试在 in_array 调用中添加第三个参数true(严格模式)。


4
这是松散比较和 type juggling 的结果。
松散比较意味着 PHP 在比较元素时使用的是 == 而不是 ===== 不会比较两个变量类型是否相等,只比较它们的值,而 === 会确保它们在类型和值上匹配(例如比较 0 == FALSE0 === FALSE)。
因此,基本上,您的 in_array 函数正在检查:
0 == 'Bye'
0 == 'Hey'
0 == 77

请注意,由于您创建数组的方式,52将会丢失。
因此,请注意如果您执行以下操作:
print (0 == 'Bye');

你将得到1。 显然,PHP正在对“Bye”进行type juggling,将其转换为0,这与将字符串转换为int的情况相同,例如(int) 'string'将等于0。 String conversion to numbers doc(重点添加)提供了具体的参考: 。

该值由字符串的初始部分给出。如果字符串以有效的数字数据开头,则使用该值。 否则,该值将为0(零)。有效的数字数据是可选符号,后跟一个或多个数字(可选包含小数点),后跟可选指数。指数是“e”或“E”,后跟一个或多个数字。

显然,整数类型优先于字符串类型(即它可以通过将int 0转换为字符串来执行比较,这将返回False)。 这在比较运算符文档中说明:

如果您将数字与字符串进行比较或比较涉及数字字符串,则每个字符串都会转换为数字,并按数字执行比较。

感谢一个有趣的问题,让我做了一些研究并学到了新东西!

感谢您的详细解释。我遇到了这篇文章中描述的问题,但无法弄清楚为什么PHP会做出这样的行为。不确定如何记住这一点,因为这似乎与PHP的工作方式完全相反。但是,您的全面解释让我的大脑有了“模糊回忆”此类错误的机会。感谢您抽出时间进行研究,找出所有这些问题的答案! - David M

1

in_array 应该用于索引数组([0]、[1]、[2] 等),而不是像您定义的字典(键值存储)。

如果您想检查您的数组 $arr 是否包含 '0',请尝试使用 PHP 函数 array_key_exists - http://php.net/manual/en/function.array-key-exists.php

var_dump(array_key_exists(0, $arr));

2
in_array对数组是否有索引没有限制;它所做的只是检查数组中(无论是索引还是哈希)的值是否与needle匹配。 - ernie

0

类型比较(第三个参数)需要更多的系统资源和时间。 只需这样做:

$x=0;
$result=in_array($x.'',array('ABC','BAC','12c','54'));
var_dump($result);

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