在对array_uintersect文档的评论中指出,回调函数必须返回 -1 ($a < $b)、0 ($a === $b) 或 1 ($a > $b)
回调函数的目的是比较 $a 和 $b 以确定是否将它们包含在交集中,或者排除它们。那么为什么返回 -1、0 或 1 而不是简单的布尔值呢?
这是我想要实现的一些(工作)示例代码,我只是好奇它为什么会这样工作。
在对array_uintersect文档的评论中指出,回调函数必须返回 -1 ($a < $b)、0 ($a === $b) 或 1 ($a > $b)
回调函数的目的是比较 $a 和 $b 以确定是否将它们包含在交集中,或者排除它们。那么为什么返回 -1、0 或 1 而不是简单的布尔值呢?
这是我想要实现的一些(工作)示例代码,我只是好奇它为什么会这样工作。
值得一提的是,在您的数组输入上的操作比人们希望的array_uintersect()
还要奇怪。人们期望调用会导致每个条目 from和每个条目 from 每次比较一次(优化在找到第一个交叉点后停止对条目的比较)。任何理智的人都会期望每个条目都会出现在回调的参数中,并且每个条目都会出现在它的参数中。array_uintersect($firstArray, $secondArray, function ($a, $b) {})
$firstArray
$secondArray
$firstArray
$a
$secondArray
$b
事实并非如此!信不信由你,php 对您的回调的第一次调用已经$a
设置$b
为$firstArray
! 您正在调用一个以数组交集命名的函数,但该函数还会比较各个数组中的条目,而不是简单地在数组之间进行比较。真是让人头疼。
因此,array_uintersect
不能替代以下块。用户当心。
$intersection = [];
foreach ($firstArray as $a) {
foreach ($secondArray as $b) {
if (user_compare_function($a, $b) === 0) {
$intersection[] = $a;
break;
}
}
}
我认为原因在于 PHP Sourceusort
和array_uintersect
其他类似的用户回调比较函数是php_array_user_compare
xref: /PHP_5_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}
retval
如果您查看,这将使用which 是一个整数来比较函数
retval < 0 ? -1 : retval > 0 ? 1 : 0
如果您使用的是布尔值并且需要转换,它只能给出0
或1
例子
var_dump((int) true); // 1
var_dump((int) false); // 0
这意味着您可能能够boolean
在相交期间逃脱,因为仅$a === $b = 0
需要 where 而不是其他实现 retval < 0
在幕后,是对 C 函数的调用zend_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 会查看公共对象的值以进行比较。这实际上是现在内部列表上的一个讨论点!