PHP:当使用usort()时,数组项是如何传递给值比较函数的


PHP: How are array items passed to the value compare function when using usort()?

我试图了解在使用usort()时,数组中的项是如何传递给我的值比较函数的。每次迭代的$x$y值的打印输出如下:

迭代1:

// $x
array(2) { ["k1"]=> int(21) ["k2"]=> string(1) "e" }
// $y
array(2) { ["k1"]=> int(920) ["k2"]=> string(1) "z" }

迭代2:

// $x
array(2) { ["k1"]=> int(842) ["k2"]=> string(1) "t" }
// $y
array(2) { ["k1"]=> int(21) ["k2"]=> string(1) "e" } 

迭代3:

// $x
array(2) { ["k1"]=> int(920) ["k2"]=> string(1) "z" } 
// $y
array(2) { ["k1"]=> int(21) ["k2"]=> string(1) "e" } 

迭代4:

// $x
array(2) { ["k1"]=> int(842) ["k2"]=> string(1) "t" } 
// $y
array(2) { ["k1"]=> int(920) ["k2"]=> string(1) "z" } 

我的数据:

$data = array(
    array( 'k1' => 920, 'k2' => 'z' ),
    array( 'k1' => 21, 'k2' => 'e' ),
    array( 'k1' => 842, 'k2' => 't' )
);

我的自定义功能:

function value_compare_func( $x, $y ) {
    if ( $x['k1'] > $y['k1'] ) {
        return true;
    } elseif ( $x['k1'] < $y['k1'] ) {
        return false;
    } else {
        return 0;
    }
}

排序数组:

usort( $data, 'value_compare_function' );

对于第一次迭代,$x['k1']$data[1]['k1']$y['k1']$data[0][k1]。为什么我的$data数组中的项没有按顺序传递给value_compare_func()?例如,在第一次迭代中,我希望$x['k1']$data[0]['k1']$y['k1']$data[1]['k1'],但事实并非如此。

如何将这些项传递给比较函数需要了解快速排序算法。其要点是,数组中的某个元素被指定为轴心(实际上它可以是任何元素,但在有效的实现中,它通常是中值元素),然后在轴心的两侧进行比较以对数组进行排序。

这基本上是usort在PHP中的底层实现。

因此,试图观察元素传递给比较函数的顺序是相对无用的。顺序完全不重要。重要的是,您可以放心,它们将始终根据回调函数返回的内容进行正确排序。

这里需要注意的重要一点是,手册明确警告不要因为特定原因从回调返回非整数的值(它们将被强制转换为整数),在您的示例中,您将从回调返回一个布尔false,当强制转换为integer时,它将变为0。由于0表示两个值相等,因此您不会也不应该在此处期望一个正确排序的数组。

始终确保在回调中返回$a > $b时的整数值1,在$a < $b时的整值-1,以及在$a == $b时的整数0

compare函数应该返回一个数值。由于返回布尔值,因此比较将变为不可预测的false == 0,因此在排序中会丢失两者之间的区别。

您应该更改您的代码如下:

function value_compare_func( $x, $y ) {
    if ( $x['k1'] > $y['k1'] ) {
        return 1;
     } elseif ( $x['k1'] < $y['k1'] ) {
         return -1;
     } else {
         return 0;
     }
 }

并且结果将更加合乎逻辑。