|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2002-05-18 08:36 UTC] fcartegnie at nordnet dot fr
I used to make sorts with usort and calling the function below. This was working on the last versions but not anymore on the 4.2.1 :/ which outputs strange result.
function sort_function($a, $b)
{
if ((($a["livre"]/$a["quantite"]) == ($b["livre"]/$b["quantite"])) || $a["nom"] != $b["nom"]) return 0;
return (($a["livre"]/$a["quantite"]) < ($b["livre"]/$b["quantite"])) ? -1 : 1;
}
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Mon Oct 27 21:00:02 2025 UTC |
<?php /* let's define some array elements For example, 3 products (A,B,C) with different price (livre) */ $elt["nom"]="A"; $elt["livre"]=10; $elt["quantite"]=1; $ar[]=$elt; $elt["nom"]="A"; $elt["livre"]=9; $elt["quantite"]=1; $ar[]=$elt; $elt["nom"]="A"; $elt["livre"]=7; $elt["quantite"]=1; $ar[]=$elt; $elt["nom"]="A"; $elt["livre"]=11; $elt["quantite"]=1; $ar[]=$elt; $elt["nom"]="A"; $elt["livre"]=101; $elt["quantite"]=1; $ar[]=$elt; $elt["nom"]="B"; $elt["livre"]=104; $elt["quantite"]=1; $ar[]=$elt; $elt["nom"]="C"; $elt["livre"]=101; $elt["quantite"]=1; $ar[]=$elt; /* Our sort function only swap 2 values if the name is the same and the first price is higher than second As we give a 'nom' field sorted alphabetically array, we might get the result : A7 A9 A10 A11 A101 B104 C101 Which is the result in php 4.0.6 But the result un php 4.2.1 is : C101 B104 A7 A9 A10 A11 A101 */ function sort_function($a, $b) { if ((($a["livre"]/$a["quantite"]) == ($b["livre"]/$b["quantite"])) || $a["nom"] != $b["nom"]) return 0; return (($a["livre"]/$a["quantite"]) < ($b["livre"]/$b["quantite"])) ? -1 : 1; } /* This is a 2nd function, which always returns that elements are equal. So it might not change the array... If you try this alternate function, you'll see that the array is modified to : B104 C101 A101 A11 A9 A7 A10 ??????! really strange behaviour */ function sort_function_void($a, $b) { return 0; } echo "<HTML><PRE>UnSorted:\n"; for ($i=0;$i<sizeof($ar);$i++) echo $ar[$i]["nom"].$ar[$i]["livre"]."\n"; usort($ar, sort_function); //usort($ar, sort_function_void); echo "Sorted:\n"; for ($i=0;$i<sizeof($ar);$i++) echo $ar[$i]["nom"].$ar[$i]["livre"]."\n"; ?>I've hit the sort problem too... I tried to reproduce it in a few way and I have to say that sometimes it seems to work (sort correctly) some not... unfortunately I can only contribute with a complex routine I use to sort site navigation menus (that it's the only one it always fails on V4.2.1 and works happily in 4.0.6). For the result: on the left side the table shows the tree as is (and is already sorted) - on the right the same tree after sorting (that indeed is not). <? $d = array( array(2, 0, 8, 1, 0, "branch A", "1", "12,8,0,0,0,0,0"), array(2, 0, 9, 1, 0, "branch B", "1", "12,9,0,0,0,0,0"), array(2, 0, 10, 1, 0, "branch C", "1", "12,10,0,0,0,0,0"), array(2, 0, 11, 1, 0, "branch D", "1", "12,11,0,0,0,0,0"), array(2, 0, 12, 1, 0, "branch E", "1", "12,12,0,0,0,0,0"), array(2, 0, 13, 1, 0, "branch F", "1", "12,13,0,0,0,0,0"), array(2, 0, 14, 1, 0, "branch G", "1", "12,14,0,0,0,0,0"), array(2, 0, 15, 1, 0, "branch H", "1", "12,15,0,0,0,0,0"), array(2, 0, 16, 1, 0, "branch I", "1", "12,16,0,0,0,0,0"), array(2, 0, 17, 1, 0, "branch J", "1", "12,17,0,0,0,0,0"), array(2, 0, 18, 1, 0, "branch K", "1", "12,18,0,0,0,0,0"), array(2, 0, 19, 1, 0, "branch L", "1", "12,19,0,0,0,0,0"), array(2, 0, 20, 1, 0, "branch M", "1", "12,20,0,0,0,0,0"), array(2, 0, 21, 1, 0, "branch N", "1", "12,21,0,0,0,0,0"), array(2, 0, 155, 1, 0, "branch O", "1", "12,155,0,0,0,0,0"), array(2, 0, 163, 1, 0, "branch P", "1", "12,163,0,0,0,0,0"), array(2, 0, 981, 1, 0, "branch Q", "1b", "12,981,0,0,0,0,0"), array(3, 0, 982, 981, 0, "under branch Q", "2", "12,981,982,0,0,0,0"), array(3, 0, 983, 981, 0, "under branch Q too", "2", "12,981,983,0,0,0,0") ); function sort_level($a, $b) { // sort navigation array // indexes : [0] level, [1] order, [2] tree_id, [3] parent_id, [4] parent_ord // (unused) [5] descr, [6] class, [7] navigation if ($a[0] == 2) { // a at second level if ($b[0] == 2) { // both a and b at second level if ($a[1] == $b[1]) { // a and b at same level, same order if ($a[2] == $b[2]) { // same level, same order, same tree_id (???) return 0; } else { // return according to tree_id return ($a[2] > $b[2]) ? 1 : -1; } } else { // return according to order (in same level) return ($a[1] > $b[1]) ? 1 : -1; } } else { // a at second level, b at third if ($a[2] == $b[3]) { // b is child of a return -1; } else { // return according to a and b's parent order return ($a[1] > $b[4]) ? 1 : -1; } } } else { // a at third level if ($b[0] == 3) { // both a and b at third level if ($a[1] == $b[1]) { // a and b at same level, same order if ($a[2] == $b[2]) { // same level, same order, same tree_id (???) return 0; } else { // return according to tree_id return ($a[2] > $b[2]) ? 1 : -1; } } else { // return according to order (in same level) return ($a[1] > $b[1]) ? 1 : -1; } } else { // b at second level, a at third if ($a[3] == $b[2]) { // a is child of b return 1; } else { // return according to a's parent and b order return ($a[4] > $b[1]) ? 1 : -1; } } } // just can't get here ! } function dotable($t) { print "<table border=1 cellspacing=1 cellpadding=5>\n"; for ($i = 0; $i < count($t); $i++) { print " <tr>"; for ($j = 0; $j < count($t[$i]); $j++) { print " <td>".$t[$i][$j]."</td>\n"; } print " </tr>\n"; } print "</table>\n"; return; } ?> <html> <head> </head> <body> <table border=1 cellspacing=1 cellpadding=5> <tr> <td><? dotable($d); ?></td> <? usort($d, "sort_level"); ?> <td><? dotable($d); ?></td> </tr> </table> </body> </html>Hi all. I think this is still a bug as I can partially recreate the behaviour that fcartegnie@nordnet.fr reported. On a script that uses a function passed to usort that always returns 0 (implying equal values), I am seeing that the order of elements in the array is being modified. The only reason I consider this a bug is because that was not the case in the earlier version I tested. Here are the details: -The code I used on both systems: <? //The function usort will use. Returns 0 implying that every comparison is equal. function fake_sort($left, $right){ return 0; } //create our aTest array and add some data to it $aTest = array(); $aTest[] = "E"; $aTest[] = "C"; $aTest[] = "B"; $aTest[] = "D"; $aTest[] = "A"; //output the order of elements in the array before running usort on it. reset($aTest); echo "Before usort()<br>\n"; while(list($key, $val) = each($aTest)){ echo "Value: ".$val."<br>\n"; } //sort it usort($aTest, "fake_sort"); //output the order of elements in the array after running usort on it. reset($aTest); echo "<p>After usort()<br>\n"; while(list($key, $val) = each($aTest)){ echo "Value: ".$val."<br>\n"; } ?> -Incorrect (unexpected) Results System: RH 7.2, Apache 1.3.26, PHP 4.2.1 Output: Before usort() Value: E Value: C Value: B Value: D Value: A After usort() Value: A Value: D Value: B Value: C Value: E -Correct (expected) Results System: RH 7.2, Apache 1.3.26, PHP 4.1.2 Output: Before usort() Value: E Value: C Value: B Value: D Value: A After usort() Value: E Value: C Value: B Value: D Value: A