preserve键顺序(稳定排序)与PHP的uasort排序时 [英] Preserve key order (stable sort) when sorting with PHP's uasort

查看:125
本文介绍了preserve键顺序(稳定排序)与PHP的uasort排序时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题实际上是从另外一个灵感在这里SO,我想扩大它一下。

有关联数组在PHP中是有可能的值进行排序,但其中的值等于preserve原来的键顺序,使用一个内置的排序功能,PHP的一个(或多个)<? / EM>

下面是一个脚本我用来测试可能的解决方案(没有找到任何):

 &LT; PHP
标题(内容类型:text / plain的);
为($ i = 0; $ I小于10; $ I ++){
    [键 - '$ i]于$常用3 =兰特(1,5)* 10;
}
uasort($改编,函数($ A,$ B){
    //排序情况可以去这里//
    //尝试:回报($ A == $ B)1:($ A  -  $ B); //
    //尝试:返回$ a取代; = $ B; //
});
的print_r($ ARR);
?&GT;
 

陷阱:由于密钥有序原始数组中,请不要试图提出任何依键恢复到原来的顺序。我与他们奉命更容易直观地检查他们的输出顺序的例子。

感谢您的测试的输入,
阿林

解决方案

由于 PHP之后,PHP 4.1.0 不支持稳定的排序,你需要编写自己的功能。

这似乎做什么你问:<一href="http://www.php.net/manual/en/function.usort.php#38827">http://www.php.net/manual/en/function.usort.php#38827

  

由于手册说,如果两个成员比较结果相等,它们的排序数组中的顺序是不确定的。这意味着,所使用的排序是不是稳定,并可能改变该比较是相等的元素的顺序

     

有时候,你真的需要一个稳定的排序。例如,如果一个字段排序列表,然后重新排序另一个领域,但不希望失去从previous字段的顺序。在这种情况下,最好使用usort一个比较函数,它接受两个领域考虑,但如果你不能这样做,那么使用了以下功能。这是一个合并排序,这是保证为O(n *日志(N))的复杂性,这意味着当你使用更大的列表(不像冒泡排序和插入排序,这是为O(n ^ 2)),它保持相当快的均匀。

 &LT; PHP
功能归并(安培; $数组,$ cmp_function ='STRCMP'){
    //数组的大小和其中的; 2无需采取行动。
    如果(计数($阵列)2)回报;
    //劈成两半数组
    $中途=计数($阵列)/ 2;
    $ ARRAY1 = array_slice($阵,0,$一半);
    $ ARRAY2 = array_slice($数组,$一半);
    //递归到两个半部排序
    归并($ ARRAY1,$ cmp_function);
    归并($ ARRAY2,$ cmp_function);
    //如果所有的$ ARRAY1为&lt; =所有$ ARRAY2,只是追加他们。
    如果(call_user_func($ cmp_function,端($ ARRAY1),$ ARRAY2 [0])&小于1){
        $阵列= array_merge($ array1中,$ ARRAY2);
        返回;
    }
    //合并两个有序阵列成一个排序的数组
    $阵列=阵列();
    $ ptr1的= $ PTR2 = 0;
    而($ ptr1的&LT;计数($ ARRAY1)及和放大器; $ PTR2&LT;计数($ ARRAY2)){
        如果(call_user_func($ cmp_function,$ ARRAY1 [$ ptr1的],$ ARRAY2 [$ PTR2])。1){
            $数组[] = $ ARRAY1 [$ ptr1的++];
        }
        其他 {
            $数组[] = $ ARRAY2 [$ PTR2 ++];
        }
    }
    //合并剩余
    而($ ptr1的&LT;计数($ ARRAY1))$数组[] = $ ARRAY1 [$ ptr1的++];
    而($ PTR2&LT;计数($ ARRAY2))$数组[] = $ ARRAY2 [$ PTR2 ++];
    返回;
}
?&GT;
 


同时,你可能会发现这个论坛主题有趣。

This question is actually inspired from another one here on SO and I wanted to expand it a bit.

Having an associative array in PHP is it possible to sort its values, but where the values are equal to preserve the original key order, using one (or more) of PHP's built in sort function?

Here is a script I used to test possible solutions (haven't found any):

<?php
header('Content-type: text/plain');
for($i=0;$i<10;$i++){
    $arr['key-'.$i] = rand(1,5)*10;
}
uasort($arr, function($a, $b){
    // sort condition may go here //
    // Tried: return ($a == $b)?1:($a - $b); //
    // Tried: return $a >= $b; //
});
print_r($arr);
?>

Pitfall: Because the keys are ordered in the original array, please don't be tempted to suggest any sorting by key to restore to the original order. I made the example with them ordered to be easier to visually check their order in the output.

Thank you for your tested input,
Alin

解决方案

Since PHP does not support stable sort after PHP 4.1.0, you need to write your own function.

This seems to do what you're asking: http://www.php.net/manual/en/function.usort.php#38827

As the manual says, "If two members compare as equal, their order in the sorted array is undefined." This means that the sort used is not "stable" and may change the order of elements that compare equal.

Sometimes you really do need a stable sort. For example, if you sort a list by one field, then sort it again by another field, but don't want to lose the ordering from the previous field. In that case it is better to use usort with a comparison function that takes both fields into account, but if you can't do that then use the function below. It is a merge sort, which is guaranteed O(n*log(n)) complexity, which means it stays reasonably fast even when you use larger lists (unlike bubblesort and insertion sort, which are O(n^2)).

<?php
function mergesort(&$array, $cmp_function = 'strcmp') {
    // Arrays of size < 2 require no action.
    if (count($array) < 2) return;
    // Split the array in half
    $halfway = count($array) / 2;
    $array1 = array_slice($array, 0, $halfway);
    $array2 = array_slice($array, $halfway);
    // Recurse to sort the two halves
    mergesort($array1, $cmp_function);
    mergesort($array2, $cmp_function);
    // If all of $array1 is <= all of $array2, just append them.
    if (call_user_func($cmp_function, end($array1), $array2[0]) < 1) {
        $array = array_merge($array1, $array2);
        return;
    }
    // Merge the two sorted arrays into a single sorted array
    $array = array();
    $ptr1 = $ptr2 = 0;
    while ($ptr1 < count($array1) && $ptr2 < count($array2)) {
        if (call_user_func($cmp_function, $array1[$ptr1], $array2[$ptr2]) < 1) {
            $array[] = $array1[$ptr1++];
        }
        else {
            $array[] = $array2[$ptr2++];
        }
    }
    // Merge the remainder
    while ($ptr1 < count($array1)) $array[] = $array1[$ptr1++];
    while ($ptr2 < count($array2)) $array[] = $array2[$ptr2++];
    return;
}
?>


Also, you may find this forum thread interesting.

这篇关于preserve键顺序(稳定排序)与PHP的uasort排序时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆