2

在对array_uintersect文档的评论中指出,回调函数必须返回 -1 ($a < $b)、0 ($a === $b) 或 1 ($a > $b)

回调函数的目的是比较 $a 和 $b 以确定是否将它们包含在交集中,或者排除它们。那么为什么返回 -1、0 或 1 而不是简单的布尔值呢?

这是我想要实现的一些(工作)示例代码,我只是好奇它为什么会这样工作。

4

4 回答 4

4

值得一提的是,在您的数组输入上的操作人们希望的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;
        }
    }
}
于 2016-08-08T21:05:37.417 回答
1

我认为原因在于 PHP Sourceusortarray_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

如果您使用的是布尔值并且需要转换,它只能给出01

例子

var_dump((int) true); // 1
var_dump((int) false); // 0

这意味着您可能能够boolean在相交期间逃脱,因为仅$a === $b = 0需要 where 而不是其他实现 retval < 0

于 2012-11-10T02:51:47.080 回答
1

梨替换接受回调,只返回一个布尔值。php函数没有。所以原因可能是php中的优化。你可以在这里检查一下

于 2012-11-10T02:54:12.510 回答
1

在幕后,是对 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 会查看公共对象的值以进行比较。这实际上是现在内部列表上的一个讨论点!

于 2012-11-10T03:12:21.517 回答