为什么在 PHP 中使用循环创建的数组无法使用 in_array 函数?

5

为什么用循环创建的 PHP 数组无法使用 in_array 函数?

下面这段代码会显示 Match found

<?php
for ($i = 0; $i < 10; ++$i) {
    $people[] = $i;
}    
if (in_array('test', $people))
  {
  echo "Match found";
  }
else
  {
  echo "Match not found";
  }
?>

以下代码显示未找到匹配项

<?php
$people = array("0","1","2","3","4","5","6","7","8","9");
if (in_array('test', $people))
  {
  echo "Match found";
  }
else
  {
  echo "Match not found";
  }
?>

如何解决第一个代码显示“未找到匹配项”的问题。

尝试使用严格检查 in_array('test', $people, true) - bansi
3个回答

7
因为在您的第一个数组中有整数,而默认情况下 in_array() 进行的是非严格类型比较,它只考虑了有限数量的类型对。因此,它会对您的 needle 进行静默转换为整数,结果为 0,并在数组中找到它。
为避免此错误,只需将 TRUE 作为第三个参数传递给 in_array(),以进行严格类型比较,例如:
if (in_array('test', $people<b>, TRUE</b>))

1
是的和不是的;-) "默认情况下,in_array() 不会检查元素的类型" 这是不正确的。非严格比较的默认比较函数仍然考虑类型。但它只考虑了相对有限数量的类型对。默认情况下将两个操作数转换为数字 => test->0 === 0 :-S - VolkerK
为什么使用这段代码后仍然显示“未找到匹配项”? - mongmong seesee
@mongmongseesee 因为你现在做的是严格比较,所以 "5" !== 5 - Rizier123
@VolkerK 重写了它,并链接到实际的源代码比较函数。 - Rizier123
@VolkerK ASCII箭头已经过时了 ;) 使用Unicode箭头 - Rizier123
我距离40岁还有三个月,忍一忍吧;-) - VolkerK

2

您只需更改

$people[] = $i; ---by--> $people[] = "$i";

然后你需要比较字符串。
<?php

for ($i = 0; $i < 10; ++$i) {
    $people[] = "$i";

}   

if (in_array('test', $people))
  {
  echo "Match found";
  }
else
  {
  echo "Match not found";
  }
?>

2

你已经得到了解决方法,让我来补充一个更加技术性的答案:为什么会发生这种情况...

这种行为源自 ZEND_API int compare_function(..) 的独特实现方式。
当你调用 in_array(needle, haystack, strict) 时,如果 $strict=true 参数没有设置,则会使用 此函数比较 needle 和 haystack 中的每个元素,直到找到匹配项为止。
在这里,你的 needle 是一个字符串,而 haystack 中的元素是整数。
让我们简单看一下 compare_function()

while(1) {
    switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
        case TYPE_PAIR(IS_LONG, IS_LONG):
            ZVAL_LONG(result, Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)?-1:0));
                return SUCCESS;
        [...more CASEs that don't apply on the first iteration of the while-loop...]
        default:
          [...some if-elseif cases that do not apply on the first iteration of the while-loop...]
                } else {
                    zendi_convert_scalar_to_number(op1, op1_copy, result);
                    zendi_convert_scalar_to_number(op2, op2_copy, result);
                    converted = 1;
                }
[...]

当这段代码第一次执行时,op1~'test'op2~0。(其中 ~ 表示“大约是”,因为内部表示有点不同,但在这里并不重要。)
但没有 TYPE_PAIR(IS_STRING, IS_LONG) 的情况,所以它会命中默认分支。有一些 if 条件来处理对象,但是两个操作数都不是对象,所以它到达了将操作数转换的部分(仅一次)。
再次没有任何 if 条件适用,所以它进入最后一个 else 分支,将 两个 操作数都转换为数字。
'test' 被转换为 0,而 0 保持为 0
然后 while 循环再次执行,现在是 TYPE_PAIR(IS_LONG,IS_LONG) - 第一个 case。现在 两个 操作数相等,因此 in_array() 返回 true。

...是的,我也觉得很混乱;-)


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