PHP数组比较:为什么数组的回调函数必须返回-1、0或1?
在文档的注释中指出,回调函数必须返回-1($a<$b)、0($a===$b)或1($a>$b) 回调函数的目的是比较$a和$b,以确定是将它们包括在交叉点中,还是排除它们。那么为什么返回-1、0或1而不是简单的布尔值呢PHP数组比较:为什么数组的回调函数必须返回-1、0或1?,php,arrays,multidimensional-array,comparison,Php,Arrays,Multidimensional Array,Comparison,在文档的注释中指出,回调函数必须返回-1($a$b) 回调函数的目的是比较$a和$b,以确定是将它们包括在交叉点中,还是排除它们。那么为什么返回-1、0或1而不是简单的布尔值呢 以下是我想要实现的一些(工作)功能,我只是好奇它为什么会这样工作。我认为原因在于PHP源代码usort和array\u uintersect以及其他类似的用户回调比较函数,即PHP\u array\u user\u compare xref:/PHP\u 5\u 3/ext/standard/array.c 568sta
以下是我想要实现的一些(工作)功能,我只是好奇它为什么会这样工作。我认为原因在于PHP源代码
usort
和array\u uintersect
以及其他类似的用户回调比较函数,即PHP\u array\u user\u compare
xref:/PHP\u 5\u 3/ext/standard/array.c
568static int php_array_user_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */
569{
570 Bucket *f;
571 Bucket *s;
572 zval **args[2];
573 zval *retval_ptr = NULL;
574
575 f = *((Bucket **) a);
576 s = *((Bucket **) b);
577
578 args[0] = (zval **) f->pData;
579 args[1] = (zval **) s->pData;
580
581 BG(user_compare_fci).param_count = 2;
582 BG(user_compare_fci).params = args;
583 BG(user_compare_fci).retval_ptr_ptr = &retval_ptr;
584 BG(user_compare_fci).no_separation = 0;
585 if (zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache) TSRMLS_CC) == SUCCESS && retval_ptr) {
586 long retval;
587
588 convert_to_long_ex(&retval_ptr);
589 retval = Z_LVAL_P(retval_ptr);
590 zval_ptr_dtor(&retval_ptr);
591 return retval < 0 ? -1 : retval > 0 ? 1 : 0;
592 } else {
593 return 0;
594 }
595}
如果您使用的是布尔值且需要进行转换,则只能给出0
或1
范例
var_dump((int) true); // 1
var_dump((int) false); // 0
这意味着您可能能够在intersect期间避开boolean
,因为只有$a===$b=0
是必需的,但对于retval<0
只返回布尔值的接受回调的其他实现则不需要。
php函数不支持。
所以原因可能是php中的优化。您可以在引擎盖下检查此是对C函数的调用
zend\u qsort
if (behavior == INTERSECT_NORMAL) {
zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *), intersect_data_compare_func TSRMLS_CC);
} else if (behavior & INTERSECT_ASSOC) { /* triggered also when INTERSECT_KEY */
zend_qsort((void *) lists[i], hash->nNumOfElements, sizeof(Bucket *), intersect_key_compare_func TSRMLS_CC);
}
对这些关系非常敏感,因此它可以执行其算法的分区组件。与轴具有相同值的项目将放置在轴的相邻位置或任一侧
有趣的是,大于比较运算符
用于对象比较,这是一种未记录的行为。根据一条评论,PHP查看公共对象的值进行比较。这实际上是现在 值得一提的是,array\u uintersect()
对数组输入的操作甚至比人们希望的更奇怪。人们期望调用array\u uintersect($firstArray,$secondArray,function($a,$b){})
将导致$firstArray
中的每个条目和$secondArray
中的每个条目分别进行一次比较(在找到第一个交叉点后,对条目停止比较进行优化)。任何理智的人都会期望,$firstArray
的每个条目都会进入回调的$a
参数,而$secondArray
的每个条目都会进入其$b
参数
事实并非如此!信不信由你,php对回调函数的第一次调用将$a
和$b
都设置为$firstArray
中的条目!您正在调用一个以数组的交集命名的函数,但该函数也会比较单个数组中的条目,而不仅仅是比较数组之间的条目。这真是让人麻木
因此,array\u uintersect
不是以下块的替代品。用户要当心
$intersection = [];
foreach ($firstArray as $a) {
foreach ($secondArray as $b) {
if (user_compare_function($a, $b) === 0) {
$intersection[] = $a;
break;
}
}
}
但是为什么需要三个值呢?我认为这3个条件是用某种内部排序来考虑的:<代码> -1 ,<代码> 0 和<代码> 1 < /COD>实际上是典型的排序标准。抱歉,我没有考虑这个特殊情况。在这种情况下,只需要两个值:一个值是否存在于另一个数组中。排序函数确实需要知道一个值是否不同,因为它是大还是小。为了避免有两种语义不同的回调,它们只是让array_uintersect()使用与usort()相同的类型。也许它们只是想在数组排序函数方面保持一致。编辑:基本上是cleong说的;)bool
function myfunction($v1,$v2){if($v1===$v2)返回0;//if($v1>$v2)返回1;//取消注释以查看正确的结果,否则返回-1;}$a1=array(2,4,1)$a2=阵列(3,1,4);打印(数组接口($a1,$a2,“myfunction”)简单地说,在什么情况下,array\u uintersect()
会给出与上面代码不同的结果?
$intersection = [];
foreach ($firstArray as $a) {
foreach ($secondArray as $b) {
if (user_compare_function($a, $b) === 0) {
$intersection[] = $a;
break;
}
}
}