<?php
// Comparison function
function cmp($a, $b) {
    if ($a == $b) {
        return 0;
    }
    return ($a < $b) ? -1 : 1;
}// Array to be sorted
$array = array('a' => 4, 'b' => 8, 'c' => -1, 'd' => -9, 'e' => 2, 'f' => 5, 'g' => 3, 'h' => -4);
print_r($array);// Sort and print the resulting array
uasort($array, 'cmp');
print_r($array);
?> issue1:第一次运行cmp方法时候的$a,$b是$array中的哪两个值,是随机的吗?
issue2:cmp总共运行多少?
issue:3怎么查看uasort的源码?

解决方案 »

  1.   

    源码在 array.c 中算法像是希尔排序
      

  2.   

    无论采用何种排序算法,你总是要比较两个元素的大小的
    uasort 就是把比较元素大小的任务交给用户函数来进行
      

  3.   


    现在碰到一问题:
    我本地是apache,测试站nigix。 对同一个数组用uasort排序得出来的结果不一样。
    貌似两个环境下同一个数组元素之间比较的顺序以及总共比较的次数都不一样。
      

  4.   


    上面贴出来的代码里面的数组比较简单,在两个环境下的结果是一样的,但是比较顺序是不一样的。
    排序比较方法:
        protected function _compareTotals($a, $b)
        {
            $aCode = $a['_code'];
            $bCode = $b['_code'];
            if (in_array($aCode, $b['after']) || in_array($bCode, $a['before'])) {
                $res = -1;
            } elseif (in_array($bCode, $a['after']) || in_array($aCode, $b['before'])) {
                $res = 1;
            } else {
                $res = 0;
            }
            return $res;
        }
    出问题的数组:
    array (size=11)
      'nominal' => 
        array (size=5)
          'class' => string 'sales/quote_address_total_nominal' (length=33)
          'before' => 
            array (size=2)
              0 => string 'subtotal' (length=8)
              1 => string 'grand_total' (length=11)
          'renderer' => string 'checkout/total_nominal' (length=22)
          'after' => 
            array (size=0)
              empty
          '_code' => string 'nominal' (length=7)
      'subtotal' => 
        array (size=6)
          'class' => string 'sales/quote_address_total_subtotal' (length=34)
          'after' => 
            array (size=1)
              0 => string 'nominal' (length=7)
          'before' => 
            array (size=7)
              0 => string 'grand_total' (length=11)
              1 => string 'shipping' (length=8)
              2 => string 'freeshipping' (length=12)
              3 => string 'tax_subtotal' (length=12)
              4 => string 'discount' (length=8)
              5 => string 'tax' (length=3)
              6 => string 'weee' (length=4)
          'renderer' => string 'tax/checkout_subtotal' (length=21)
          'admin_renderer' => string 'adminhtml/sales_order_create_totals_subtotal' (length=44)
          '_code' => string 'subtotal' (length=8)
      'shipping' => 
        array (size=6)
          'class' => string 'sales/quote_address_total_shipping' (length=34)
          'after' => 
            array (size=5)
              0 => string 'subtotal' (length=8)
              1 => string 'freeshipping' (length=12)
              2 => string 'tax_subtotal' (length=12)
              3 => string 'nominal' (length=7)
              4 => string 'weee' (length=4)
          'before' => 
            array (size=4)
              0 => string 'grand_total' (length=11)
              1 => string 'discount' (length=8)
              2 => string 'tax_shipping' (length=12)
              3 => string 'tax' (length=3)
          'renderer' => string 'tax/checkout_shipping' (length=21)
          'admin_renderer' => string 'adminhtml/sales_order_create_totals_shipping' (length=44)
          '_code' => string 'shipping' (length=8)
      'grand_total' => 
        array (size=6)
          'class' => string 'sales/quote_address_total_grand' (length=31)
          'after' => 
            array (size=7)
              0 => string 'subtotal' (length=8)
              1 => string 'nominal' (length=7)
              2 => string 'shipping' (length=8)
              3 => string 'freeshipping' (length=12)
              4 => string 'tax_subtotal' (length=12)
              5 => string 'discount' (length=8)
              6 => string 'tax' (length=3)
          'renderer' => string 'tax/checkout_grandtotal' (length=23)
          'admin_renderer' => string 'adminhtml/sales_order_create_totals_grandtotal' (length=46)
          'before' => 
            array (size=0)
              empty
          '_code' => string 'grand_total' (length=11)
      'msrp' => 
        array (size=4)
          'class' => string 'sales/quote_address_total_msrp' (length=30)
          'before' => 
            array (size=0)
              empty
          'after' => 
            array (size=0)
              empty
          '_code' => string 'msrp' (length=4)
      'freeshipping' => 
        array (size=4)
          'class' => string 'salesrule/quote_freeshipping' (length=28)
          'after' => 
            array (size=2)
              0 => string 'subtotal' (length=8)
              1 => string 'nominal' (length=7)
          'before' => 
            array (size=5)
              0 => string 'tax_subtotal' (length=12)
              1 => string 'shipping' (length=8)
              2 => string 'grand_total' (length=11)
              3 => string 'tax' (length=3)
              4 => string 'discount' (length=8)
          '_code' => string 'freeshipping' (length=12)
      'discount' => 
        array (size=6)
          'class' => string 'salesrule/quote_discount' (length=24)
          'after' => 
            array (size=7)
              0 => string 'subtotal' (length=8)
              1 => string 'shipping' (length=8)
              2 => string 'nominal' (length=7)
              3 => string 'freeshipping' (length=12)
              4 => string 'tax_subtotal' (length=12)
              5 => string 'tax_shipping' (length=12)
              6 => string 'weee' (length=4)
          'before' => 
            array (size=2)
              0 => string 'grand_total' (length=11)
              1 => string 'tax' (length=3)
          'renderer' => string 'tax/checkout_discount' (length=21)
          'admin_renderer' => string 'adminhtml/sales_order_create_totals_discount' (length=44)
          '_code' => string 'discount' (length=8)
      'tax_subtotal' => 
        array (size=4)
          'class' => string 'tax/sales_total_quote_subtotal' (length=30)
          'after' => 
            array (size=3)
              0 => string 'freeshipping' (length=12)
              1 => string 'subtotal' (length=8)
              3 => string 'nominal' (length=7)
          'before' => 
            array (size=6)
              0 => string 'tax' (length=3)
              1 => string 'discount' (length=8)
              2 => string 'shipping' (length=8)
              3 => string 'grand_total' (length=11)
              4 => string 'tax_shipping' (length=12)
              5 => string 'weee' (length=4)
          '_code' => string 'tax_subtotal' (length=12)
      'tax_shipping' => 
        array (size=4)
          'class' => string 'tax/sales_total_quote_shipping' (length=30)
          'after' => 
            array (size=5)
              0 => string 'shipping' (length=8)
              1 => string 'tax_subtotal' (length=12)
              2 => string 'subtotal' (length=8)
              3 => string 'freeshipping' (length=12)
              4 => string 'nominal' (length=7)
          'before' => 
            array (size=3)
              0 => string 'tax' (length=3)
              1 => string 'discount' (length=8)
              2 => string 'grand_total' (length=11)
          '_code' => string 'tax_shipping' (length=12)
      'tax' => 
        array (size=6)
          'class' => string 'tax/sales_total_quote_tax' (length=25)
          'after' => 
            array (size=8)
              0 => string 'subtotal' (length=8)
              1 => string 'shipping' (length=8)
              2 => string 'discount' (length=8)
              3 => string 'tax_subtotal' (length=12)
              4 => string 'freeshipping' (length=12)
              5 => string 'tax_shipping' (length=12)
              6 => string 'nominal' (length=7)
              7 => string 'weee' (length=4)
          'before' => 
            array (size=1)
              0 => string 'grand_total' (length=11)
          'renderer' => string 'tax/checkout_tax' (length=16)
          'admin_renderer' => string 'adminhtml/sales_order_create_totals_tax' (length=39)
          '_code' => string 'tax' (length=3)
      'weee' => 
        array (size=4)
          'class' => string 'weee/total_quote_weee' (length=21)
          'after' => 
            array (size=4)
              0 => string 'subtotal' (length=8)
              1 => string 'tax_subtotal' (length=12)
              2 => string 'nominal' (length=7)
              3 => string 'freeshipping' (length=12)
          'before' => 
            array (size=5)
              0 => string 'shipping' (length=8)
              1 => string 'tax' (length=3)
              2 => string 'discount' (length=8)
              3 => string 'grand_total' (length=11)
              4 => string 'tax_shipping' (length=12)
          '_code' => string 'weee' (length=4)本地排序结果(apache):
    array (size=11)
      0 => string 'nominal' (length=7)
      1 => string 'subtotal' (length=8)
      2 => string 'msrp' (length=4)
      3 => string 'freeshipping' (length=12)
      4 => string 'tax_subtotal' (length=12)
      5 => string 'weee' (length=4)
      6 => string 'shipping' (length=8)
      7 => string 'tax_shipping' (length=12)
      8 => string 'discount' (length=8)
      9 => string 'tax' (length=3)
      10 => string 'grand_total' (length=11)测试站排序结果(nigix):
    0:nominal
    1:subtotal
    2:shipping
    3:grand_total
    4:msrp
    5:freeshipping
    6:tax_subtotal
    7:weee
    8:tax_shipping
    9:discount
    10:tax
      

  5.   

    这有什么关系呢?两边的 php 版本不同,可能排序算法也不同
    但是无论如何,排序的规则是你定的,不会变的。所以结果也应该相同你先检查一下两边的数据是否真如你说的:是相同的
      

  6.   

    我觉得比较的顺次和次数还是有影响的:精简一下,架设需要比较的数组有三个元素,如下:$array=array($reference,$grand_total,$msrp);
    $reference=array ( 
        'reference' => array (
            'before' =>  array ( 'grand_total' ),
            'after' =>  array ('msrp'),
            '_code' =>  'reference'
           )
        );
    $grand_total=array(
        'grand_total' => array (
            'before' =>  array ( '' ),
            'after' =>  array (''),
            '_code' =>  'grand_total'
           )
    );
    $msrp=array(
        'msrp' => array (
            'before' =>  array ( '' ),
            'after' =>  array (''),
            '_code' =>  'msrp'
           )
    );  function compareTotals($a, $b)
        {
            $aCode = $a['_code'];
            $bCode = $b['_code'];
            if (in_array($aCode, $b['after']) || in_array($bCode, $a['before'])) {
                $res = -1;
            } elseif (in_array($bCode, $a['after']) || in_array($aCode, $b['before'])) {
                $res = 1;
            } else {
                $res = 0;
            }
            return $res;
      }
      uasort($array,'compareTotals');
      
      按照compareTotals的比较方法:
    只要$grand_total和$msrp进行了比较就存在一个问题,
    到底是$grand_total排在前面还是$msrp呢?这跟2=2是不一样的,如果最后的结果是取元素的‘_code’值重重新返回一个数组,
              那么这个数组里面的值的排序就可能出现“因为比较顺序和比较次数不一样,数组元素排序不一样”的情况
      

  7.   

    贴出数组的 var_export 的结果
    var_dump 的结果看不清楚
      

  8.   


    不好意思,手抖点到拍砖了
    上数组~array (
      'nominal' => 
      array (
        'class' => 'sales/quote_address_total_nominal',
        'before' => 
        array (
          0 => 'subtotal',
          1 => 'grand_total',
        ),
        'renderer' => 'checkout/total_nominal',
        'after' => 
        array (
        ),
        '_code' => 'nominal',
      ),
      'subtotal' => 
      array (
        'class' => 'sales/quote_address_total_subtotal',
        'after' => 
        array (
          0 => 'nominal',
        ),
        'before' => 
        array (
          0 => 'grand_total',
          1 => 'shipping',
          2 => 'freeshipping',
          3 => 'tax_subtotal',
          4 => 'discount',
          5 => 'tax',
          6 => 'weee',
        ),
        'renderer' => 'tax/checkout_subtotal',
        'admin_renderer' => 'adminhtml/sales_order_create_totals_subtotal',
        '_code' => 'subtotal',
      ),
      'shipping' => 
      array (
        'class' => 'sales/quote_address_total_shipping',
        'after' => 
        array (
          0 => 'subtotal',
          1 => 'freeshipping',
          2 => 'tax_subtotal',
          3 => 'nominal',
          4 => 'weee',
        ),
        'before' => 
        array (
          0 => 'grand_total',
          1 => 'discount',
          2 => 'tax_shipping',
          3 => 'tax',
        ),
        'renderer' => 'tax/checkout_shipping',
        'admin_renderer' => 'adminhtml/sales_order_create_totals_shipping',
        '_code' => 'shipping',
      ),
      'grand_total' => 
      array (
        'class' => 'sales/quote_address_total_grand',
        'after' => 
        array (
          0 => 'subtotal',
          1 => 'nominal',
          2 => 'shipping',
          3 => 'freeshipping',
          4 => 'tax_subtotal',
          5 => 'discount',
          6 => 'tax',
        ),
        'renderer' => 'tax/checkout_grandtotal',
        'admin_renderer' => 'adminhtml/sales_order_create_totals_grandtotal',
        'before' => 
        array (
        ),
        '_code' => 'grand_total',
      ),
      'msrp' => 
      array (
        'class' => 'sales/quote_address_total_msrp',
        'before' => 
        array (
        ),
        'after' => 
        array (
        ),
        '_code' => 'msrp',
      ),
      'freeshipping' => 
      array (
        'class' => 'salesrule/quote_freeshipping',
        'after' => 
        array (
          0 => 'subtotal',
          1 => 'nominal',
        ),
        'before' => 
        array (
          0 => 'tax_subtotal',
          1 => 'shipping',
          2 => 'grand_total',
          3 => 'tax',
          4 => 'discount',
        ),
        '_code' => 'freeshipping',
      ),
      'discount' => 
      array (
        'class' => 'salesrule/quote_discount',
        'after' => 
        array (
          0 => 'subtotal',
          1 => 'shipping',
          2 => 'nominal',
          3 => 'freeshipping',
          4 => 'tax_subtotal',
          5 => 'tax_shipping',
          6 => 'weee',
        ),
        'before' => 
        array (
          0 => 'grand_total',
          1 => 'tax',
        ),
        'renderer' => 'tax/checkout_discount',
        'admin_renderer' => 'adminhtml/sales_order_create_totals_discount',
        '_code' => 'discount',
      ),
      'tax_subtotal' => 
      array (
        'class' => 'tax/sales_total_quote_subtotal',
        'after' => 
        array (
          0 => 'freeshipping',
          1 => 'subtotal',
          3 => 'nominal',
        ),
        'before' => 
        array (
          0 => 'tax',
          1 => 'discount',
          2 => 'shipping',
          3 => 'grand_total',
          4 => 'tax_shipping',
          5 => 'weee',
        ),
        '_code' => 'tax_subtotal',
      ),
      'tax_shipping' => 
      array (
        'class' => 'tax/sales_total_quote_shipping',
        'after' => 
        array (
          0 => 'shipping',
          1 => 'tax_subtotal',
          2 => 'subtotal',
          3 => 'freeshipping',
          4 => 'nominal',
        ),
        'before' => 
        array (
          0 => 'tax',
          1 => 'discount',
          2 => 'grand_total',
        ),
        '_code' => 'tax_shipping',
      ),
      'tax' => 
      array (
        'class' => 'tax/sales_total_quote_tax',
        'after' => 
        array (
          0 => 'subtotal',
          1 => 'shipping',
          2 => 'discount',
          3 => 'tax_subtotal',
          4 => 'freeshipping',
          5 => 'tax_shipping',
          6 => 'nominal',
          7 => 'weee',
        ),
        'before' => 
        array (
          0 => 'grand_total',
        ),
        'renderer' => 'tax/checkout_tax',
        'admin_renderer' => 'adminhtml/sales_order_create_totals_tax',
        '_code' => 'tax',
      ),
      'weee' => 
      array (
        'class' => 'weee/total_quote_weee',
        'after' => 
        array (
          0 => 'subtotal',
          1 => 'tax_subtotal',
          2 => 'nominal',
          3 => 'freeshipping',
        ),
        'before' => 
        array (
          0 => 'shipping',
          1 => 'tax',
          2 => 'discount',
          3 => 'grand_total',
          4 => 'tax_shipping',
        ),
        '_code' => 'weee',
      ),
    )
      

  9.   

    先实测一下你 #7 的简化数据
    1、运行时将有大量 Notice:  Undefined index: _code 
      显然是有问题的
    2、在 compareTotals 中增加 print_r(array('A' => $a, 'B' => $b));
    每次传入的是形如这样的数据Array
    (
        [A] => Array
            (
                [grand_total] => Array
                    (
                        [before] => Array
                            (
                                [0] => 
                            )                    [after] => Array
                            (
                                [0] => 
                            )                    [_code] => grand_total
                    )        )    [B] => Array
            (
                [reference] => Array
                    (
                        [before] => Array
                            (
                                [0] => grand_total
                            )                    [after] => Array
                            (
                                [0] => msrp
                            )                    [_code] => reference
                    )        ))
    显然 $aCode = $a['_code']; 这样的语句是有问题的,关联键 _code 在第二维,你却从第一维取只此,已无继续测试的必要了
      

  10.   

    而你 #9 的数据是正确的,测试结果是正确的5.4.31
    排序前
    Array
    (
        [0] => nominal
        [1] => subtotal
        [2] => shipping
        [3] => grand_total
        [4] => msrp
        [5] => freeshipping
        [6] => discount
        [7] => tax_subtotal
        [8] => tax_shipping
        [9] => tax
        [10] => weee
    )
    排序后
    Array
    (
        [0] => nominal
        [1] => subtotal
        [2] => msrp
        [3] => freeshipping
        [4] => tax_subtotal
        [5] => weee
        [6] => shipping
        [7] => tax_shipping
        [8] => discount
        [9] => tax
        [10] => grand_total
    )5.6.3
    排序前
    Array
    (
        [0] => nominal
        [1] => subtotal
        [2] => shipping
        [3] => grand_total
        [4] => msrp
        [5] => freeshipping
        [6] => discount
        [7] => tax_subtotal
        [8] => tax_shipping
        [9] => tax
        [10] => weee
    )
    排序后
    Array
    (
        [0] => nominal
        [1] => subtotal
        [2] => msrp
        [3] => freeshipping
        [4] => tax_subtotal
        [5] => weee
        [6] => shipping
        [7] => tax_shipping
        [8] => discount
        [9] => tax
        [10] => grand_total
    )
      

  11.   

    4.3.4
    排序前
    Array
    (
        [0] => nominal
        [1] => subtotal
        [2] => shipping
        [3] => grand_total
        [4] => msrp
        [5] => freeshipping
        [6] => discount
        [7] => tax_subtotal
        [8] => tax_shipping
        [9] => tax
        [10] => weee
    )
    排序后
    Array
    (
        [0] => nominal
        [1] => subtotal
        [2] => msrp
        [3] => freeshipping
        [4] => tax_subtotal
        [5] => weee
        [6] => shipping
        [7] => tax_shipping
        [8] => discount
        [9] => tax
        [10] => grand_total
    )
      

  12.   


    不要意思,简化后的数组确实有问题,是不小心把简化数组的时候写错了。我的本意不是想说明比较程序能否正常运,而是想说明不同的比较顺序和比较次数是会导致排序结果不同的。我本地的apache环境确实可以把#9排序的,而且也是期望中的顺序,也就是楼主在#11楼提到的。
    问题是,在测试服务器(nigix)上排除的结果跟apche上的结果有出入。结果如下:
    本地排序结果(apache):
    array (size=11)
      0 => string 'nominal' (length=7)
      1 => string 'subtotal' (length=8)
      2 => string 'msrp' (length=4)
      3 => string 'freeshipping' (length=12)
      4 => string 'tax_subtotal' (length=12)
      5 => string 'weee' (length=4)
      6 => string 'shipping' (length=8)
      7 => string 'tax_shipping' (length=12)
      8 => string 'discount' (length=8)
      9 => string 'tax' (length=3)
      10 => string 'grand_total' (length=11)测试站排序结果(nigix):
    0:nominal
    1:subtotal
    2:shipping
    3:grand_total
    4:msrp
    5:freeshipping
    6:tax_subtotal
    7:weee
    8:tax_shipping
    9:discount
    10:tax  
      

  13.   

    那应该是服务器上的 php 有问题
    我在 #11、#12 已贴出了我手边三个版本 php 运行的结果
    你可自己对比一下,并没有什么不同之处
      

  14.   


    可能吧版主有php5.5.27吗?
      

  15.   


    在同一个php版本里面,只要把源数组的第一维的元素换下位置,排除来的就
    调换数组里面第一维度键值为“mrsp”的元素的位置,得到的排序结果就会不一样。可以证实我之前的猜测,确实跟比较的顺序和次数是相关的。可能真的是php版本的关系。