Can't understand the usort algorithm, how the user defined function gets the arguments

Because this PHP and not Java. PHP doesn’t warn about things like that.

If you want warnings like those you can have a look at static analyzers like PHPStan.

1 Like

Hi my friends,
I changed the code to the following:

 <?php function list_cmp($a, $b){ 
    global $order;
    echo '1value of dollar_a is $a=' . "$a" . "<BR>";  
    echo '2value of dollar_b is $b=' . "$b" . "<BR>";   
    foreach($order as $key => $value){        
       if($a==$value){
             echo '3b_value of dollar_a is $a=' . "$a" . "<BR>";
             return 0;
             echo '3b_value of dollar_a is $a=' . "$a" . "<BR>"; 
             break;
             echo '3c_value of dollar_a is $a=' . "$a" . "<BR>";   
       }
       if($b==$value){
             echo '4a_value of dollar_b is $b=' . "$b" . "<BR>";  
             return 1;
             echo '4b_value of dollar_b is $b=' . "$b" . "<BR>";  
             break;          
       }     echo '4c_value of dollar_b is $b=' . "$b" . "<BR>";   
    }  
    echo '5value of dollar_a is $a=' . "$a" . "<BR>";  
    echo '6value of dollar_a is $b=' . "$b" . "<BR>"; 
 }  
 $order[0] = 1; $order[1] = 3;  $order[2] = 4;  $order[3] = 2;  $array[0] = 2; $array[1] = 1;  $array[2] = 3;  $array[3] = 4;  $array[4] = 2;  $array[5] = 1;  $array[6] = 2;  usort($array, "list_cmp");  print_r($array); 
 ?>

I checked the following link:

It says that usort forms pairing, I found and lost another link of stackexchange which says that usort uses the concept of quick sort, using the above program, I got the following output:

L1_1value of dollar_a is $a=2:P1
L2_2value of dollar_b is $b=1:P2, I.e.(2, 1)
L3_4a_value of dollar_b is $b=1
L4_1value of dollar_a is $a=2:P1
L5_2value of dollar_b is $b=3:P2, i.e. (2, 3)
L6_4c_value of dollar_b is $b=3
L7_4a_value of dollar_b is $b=3
L8_1value of dollar_a is $a=1: P1
L9_2value of dollar_b is $b=3: P2, i.e. (1,3)
L10_3b_value of dollar_a is $a=1
L11_1value of dollar_a is $a=2: P1
L12_2value of dollar_b is $b=4: P2, i.e. (2, 4)
L13_4c_value of dollar_b is $b=4
L14_4c_value of dollar_b is $b=4
L15_4a_value of dollar_b is $b=4
L16_1value of dollar_a is $a=3: P1
L17_2value of dollar_b is $b=4: P2, i.e. (3, 4)
L18_4c_value of dollar_b is $b=4
L19_3b_value of dollar_a is $a=3
L20_1value of dollar_a is $a=2: P1
L21_2value of dollar_b is $b=2: P2, i.e. (2, 2)
L22_4c_value of dollar_b is $b=2
L23_4c_value of dollar_b is $b=2
L24_4c_value of dollar_b is $b=2
L25_3b_value of dollar_a is $a=2
L26_1value of dollar_a is $a=2: P1
L27_2value of dollar_b is $b=1: P2, i.e. (2, 1)
L28_4a_value of dollar_b is $b=1
L29_1value of dollar_a is $a=2: P1
L30_2value of dollar_b is $b=1: P2, i.e. (1, 2)
L31_4a_value of dollar_b is $b=1
L32_1value of dollar_a is $a=4: P1
L33_2value of dollar_b is $b=1: P2, i.e. (1, 2)
L34_4a_value of dollar_b is $b=1
L35_1value of dollar_a is $a=3: P1
L36_2value of dollar_b is $b=1: P2, i.e. (3, 1)
L37_4a_value of dollar_b is $b=1
L38_1value of dollar_a is $a=1: P1
L39_2value of dollar_b is $b=1: P2, i.e. (1, 1)
L40_3b_value of dollar_a is $a=1
L41_1value of dollar_a is $a=2: P1
L42_2value of dollar_b is $b=2: P2, i.e. (1, 2)
L43_4c_value of dollar_b is $b=2
L44_4c_value of dollar_b is $b=2
L45_4c_value of dollar_b is $b=2
L46_3b_value of dollar_a is $a=2
L47_Array ( [0] => 1 [1] => 1 [2] => 3 [3] => 4 [4] => 2 [5] => 2 [6] => 2 )

Note in the above output L1 to L47 represents the line numbers which I put afterwards. L1 and L2 forms pairs (2,1) i.e. $a =2 and $b=1. Now L4 and L5 forms pairs (2, 3), $a =2 and $b =3. Now L8 and L9 forms pairs (1,3) i.e. $a =1 and $b=3, where value 2 has gone? Somebody please guide me. Zulfi.

Please format your code the same way you’ve formatted the results - it’s unreadable as you’ve posted it. Thanks.

I’ve done it. smile

1 Like

I don’t… understand why you’re walking the array inside the list_cmp function.
What was the value of $order at the start of your sort?

1 Like

oh derp. $order is constructed in your code. I can read.

Right, so for my own sanity…

$order = [1,3,4,2];
$array = [2,1,3,4,2,1,2];

Usorting $array.

There’s a lot of nerdy deepdive you can do on how PHP implements quicksort and how it chooses and manipulates its pivot. https://www.youtube.com/watch?v=Hoixgm4-P4M here’s a demonstration of how Quicksort works. For context, PHP always chooses “the middle value of the partition” as its pivot.

Essentially, “Where value 2 has gone?” the answer is “The algorithm needs to determine if it’s in it’s correct position. So it’s got to look at other things, in order to determine the conditionals.”

Side note: Your code could be one-line written as:

usort($array, function($a,$b) use ($order) { return array_search($a,$order) <=> array_search($b, $order); });

or, if you rewrote $order to be [-1,1,4,2,3], the code becomes:

usort($array, function($a,$b) use ($order) { return $order[$a] <=> $order[$b]; });

(Little more nerdy, but i like not having to use additional searching functions!)

Or, in PHP7.4+:

usort($array, fn($a, $b) => array_search($a,$order) <=> array_search($b, $order));

:slightly_smiling_face:

1 Like

Hi m_hutley,
The order array is assigned inside the code and has following values:

`$order[0] = 1; $order[1] = 3;  $order[2] = 4;  $order[3] = 2;`

Hi droopsnoot,
I tried to edit the code, and I pressed the pencil but I can’t change anything. Its showing me the History window. Sorry.
Zulfi.

Off Topic:

It’s a bit confusing, but you need to click on the “more” symbol (...) at the bottom of the post, and that brings up another pencil icon, which allows you to edit your post. The pencil in the top right does indeed only show the edit history.

Note that there is an edit window of five hours; after that time, you will be unable to edit your post.

Don’t worry about it, @Technobear has edited it.

1 Like

Hi,
Is there any reason to use ‘break’ after ‘return’ in both the ‘if’ statements in listing shown in post#1? Will the break ever execute?

Zulfi.

You can see from post #22 that nothing executes after each of your return statements. For example when your script hits this section of code:

if($a==$value){
             echo '3b_value of dollar_a is $a=' . "$a" . "<BR>";
             return 0;
             echo '3b_value of dollar_a is $a=' . "$a" . "<BR>"; 
             break;
             echo '3c_value of dollar_a is $a=' . "$a" . "<BR>";   
       }

it actually produces this output:

L8_1value of dollar_a is $a=1: P1  - function was called here
L9_2value of dollar_b is $b=3: P2, i.e. (1,3) - second line of function
L10_3b_value of dollar_a is $a=1 - found that $a == $value, so ran first echo then return
L11_1value of dollar_a is $a=2: P1 - function was called here

It executes the first echo inside your if() clause, then it hits return so it doesn’t execute any of the other code in that block, it exits the function and then you see it being called again.

Hi all,
@droopsnoot : You are right, in the following case, echo starting with 4b is not printed. But 4c echo is outside bracket, so it is printed.

 if($b==$value){
             echo '4a_value of dollar_b is $b=' . "$b" . "<BR>";  
             return 1;
             echo '4b_value of dollar_b is $b=' . "$b" . "<BR>";  
             break;          
       }     echo '4c_value of dollar_b is $b=' . "$b" . "<BR>";

Zulfi.

Yes, that puzzled me for a moment until I realised that it was the formatting of this particular if() clause that made the 4c section outside of it, just because of the }. The previous if() clause looks pretty much the same on screen, and is just above it, but has the 3c section inside the if() clause. I’m not sure which is correct, or whether they’re intentionally different, but I’d suggest putting the 4c line on a separate line to make it easier to see.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.