|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2010-11-18 11:11 UTC] goetas at lignano dot it
Description:
------------
Starting from php 4.1.0 the sorting of arrays is not stable.
With current sort method is not possible to sort two or more times (with different sort functions) an array with consistent result.
My suggestion is to add a flag to *sort functions to choose the sorting algorithm.
I'm not a c programmer, but i think that can be changed a behavior of zend_qsort with some parameters or add a mergesort that can be used if stable sort is required.
Test script:
---------------
<?php
$a = array(
array("l"=>"B", "n"=>2),
array("l"=>"A", "n"=>1),
array("l"=>"C", "n"=>3),
array("l"=>"E", "n"=>5),
array("l"=>"D", "n"=>4),
);
usort($a, function($a1, $a2){ // alpha sort
return strcmp($a1["l"],$a2["l"]);
});
usort($a, function($a1, $a2){ // sort odd first
if($a1["n"]%2===0 && $a2["n"]%2!==0){
return -1;
}elseif($a2["n"]%2===0 && $a1["n"]%2!==0){
return 1;
}else{
return 0;
}
});
print_r($a);
Expected result:
----------------
Array
(
[0] => Array
(
[l] => B
[n] => 2
)
[1] => Array
(
[l] => D
[n] => 4
)
[2] => Array
(
[l] => A
[n] => 1
)
[3] => Array
(
[l] => C
[n] => 3
)
[4] => Array
(
[l] => E
[n] => 5
)
)
Actual result:
--------------
Array
(
[0] => Array
(
[l] => D
[n] => 4
)
[1] => Array
(
[l] => B
[n] => 2
)
[2] => Array
(
[l] => E
[n] => 5
)
[3] => Array
(
[l] => C
[n] => 3
)
[4] => Array
(
[l] => A
[n] => 1
)
)
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sat Oct 25 12:00:01 2025 UTC |
You can use this before the bug is fixed. Clement Wong function stable_uasort(&$array, $cmp_function) { if(count($array) < 2) { return; } $halfway = count($array) / 2; $array1 = array_slice($array, 0, $halfway, TRUE); $array2 = array_slice($array, $halfway, NULL, TRUE); stable_uasort($array1, $cmp_function); stable_uasort($array2, $cmp_function); if(call_user_func($cmp_function, end($array1), reset($array2)) < 1) { $array = $array1 + $array2; return; } $array = array(); reset($array1); reset($array2); while(current($array1) && current($array2)) { if(call_user_func($cmp_function, current($array1), current($array2)) < 1) { $array[key($array1)] = current($array1); next($array1); } else { $array[key($array2)] = current($array2); next($array2); } } while(current($array1)) { $array[key($array1)] = current($array1); next($array1); } while(current($array2)) { $array[key($array2)] = current($array2); next($array2); } return; }While there might be use cases demanding a stable sort, this is clearly none of them. Just sort the array with a single usort(), what is faster, by the way: <?php $a = array( array("l"=>"B", "n"=>2), array("l"=>"A", "n"=>1), array("l"=>"C", "n"=>3), array("l"=>"E", "n"=>5), array("l"=>"D", "n"=>4), ); usort($a, function($a1, $a2){ // sort even first if($a1["n"]%2===0 && $a2["n"]%2!==0){ return -1; }elseif($a2["n"]%2===0 && $a1["n"]%2!==0){ return 1; }else{// alpha sort return strcmp($a1["l"],$a2["l"]); } }); print_r($a);