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

Hi,
Kindly see the program on the following link:
usort example

``````<?php function list_cmp(\$a, \$b)
{
global \$order;
foreach(\$order as \$key => \$value)
{
if(\$a==\$value)
{
return 0;
break;
}
if(\$b==\$value)
{
return 1;
break;
}
}
}
\$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);  ?>
``````

We are not passing values of \$a and \$b. How list_cmp(âŚ) will get their values?

Zulfi.

all array sorting functions are passed two parameters under the hood; you notice you dont have to specify to walk through the entire array either.

PHP takes care of the arrangement of âwalk the array; for each pair of elements, compare and sort.â your function then must take 2 parameters (the two individual items being sorted at that given moment), and return a value that PHP can use to do the actual sorting.

Note that most comparison functions for sorting return whatâs called a âSpaceship Operator Valueâ - namely, -1,0, or 1:

if -1, A goes before B.
if 0, A and B are of equal value, and are left unsorted relative to each other.
if 1, B goes before A.

1 Like

You should imagine `usort` does something like this:

``````function usort(\$array, \$callback) {
// Get pairs of elements from \$array and loop over them
// Actual implementation of createPairsToSort is out of scope
foreach ([\$firstElement, \$secondElement] = createPairsToSort(\$array)) {
// Call the user defined function here to see how we should sort
// these two elements
\$result = \$callback(\$firstElement, \$secondElement);

if (\$result < 1) {
// update \$array so \$firstElement comes before secondElement
} else if (\$result === 0) {
// keep elements in order, leave \$array alone
} else if (\$result > 1) {
// update \$array so \$firstElement comes after secondElement
}
}
}
``````
1 Like

For those who donât know, the spaceship operator is `<=>`.

So in PHP 8 you can also sort like this:

``````usort(\$array, fn (\$first, second) => \$first <=> \$second);
``````
1 Like

[quasi-off-topic]
I know itâs called a spaceship operator for the shape. But iâve always seen it more like a seesaw. The pivotâs at 0, and itâs A (-1) and B (1) sitting on a seesaw, seeing which way it tips.
[/off-topic]

2 Likes

Hi,
What is \$value and what is \$key in the following code:

``````<?php function list_cmp(\$a, \$b)
{
global \$order;
foreach(\$order as \$key => \$value)
{
if(\$a==\$value)
{
return 0;
break;
}
if(\$b==\$value)
{
return 1;
break;
}
}
}
\$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);  ?>
``````

Try echoing \$key and see what it is. (probably want to add a line break afterward)
Then try echoing \$value.
What is the relationship between the two?

1 Like

Why do you have `\$order` involved in `list_cmp()` at all? To my view, the whole point of `usort()` is that youâve passed `\$order` into it in the first place, so itâs already sorting that array. You seem to be adding another âlayerâ of accessing the array. Youâre also bringing in a `global` there, which is my pet hate. In your code, if you want to sort a different array but use the same `list_cmp`, youâll have to have another function to use a different global array. To me, any function should be able to work with the parameters itâs passed in, and not use globals at all.

Agreed, the global is weird.

Iâd write it like this:

``````<?php

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

usort(
\$array,
function (\$a, \$b) use (\$order) {
foreach(\$order as \$key => \$value) {
if (\$a == \$value) {
return 0;
}
if (\$b == \$value) {
return 1;
}
}
}
);

print_r(\$array);
``````
1 Like

code sanity screams that you need a fall-through return.

Also shouldnt the 0 be a -1?

Not my code, just my formatting

But yes, Iâm missing a `return -1` case as well.

Hi my friends-

I tried to compile the program given in the post#1 and repeated in post#6 but I am getting the following error:

2021/10/31 22:51:28 [error] 1848#1848: *1 FastCGI sent in stderr: âPHP message: PHP Parse error: syntax error, unexpected â\$bâ (T_VARIABLE), expecting â,â or â)â in /var/www/html/w3_usortprog.php on line 1â while reading response header from upstream, client: 127.0.0.1, server: _, request: âGET /w3_usortprog.php HTTP/1.1â, upstream: âfastcgi://unix:/var/run/php/php7.2-fpm.sock:â, host: âlocalhostâ

Zulfi.

Iâm going to guess that youâve missed the comma in `(\$a, \$b)` as the error is in line 1 and it states that it was expecting either `,` or `)` in the message.

1 Like

Hi my friend-
Thanks for your response. I have put the comma.
I have attached the image of my code:

KIndly help me to solve this probrlem.

Zulfi.

If I paste your code from post #6 (I canât post the latest one because youâve put it as an image, so I presume theyâre the same) and run it in 3v4l.org PHP tester, there are no error messages and it outputs the array in what I presume is the correct order.

In some cases now Iâd be looking for control characters or similar that might have crept in to your file, maybe delete that top line and type it in again and see if that helps.

1 Like

Hi,
Thanks.
I found some extra characters on every line. I transferred my program from word to libreoffice.

I am again understanding the program according to the output.

Zulfi.

MS-Word is never a good code editor, just like itâs not a good HTML editor. Iâm using Notepad++ for PHP editing, though there are many more capable things available.

1 Like

Hi my friends,

Sorry I am still struggling with usort. After:
`global \$order;`

``````echo 'value of dollar_a is \$a=' . "\$a" . "<BR>";  //modified
echo 'value of dollar_a is \$b=' . "\$b" . "<BR>";  //modified
``````

I got the following output:

value of dollar_a is \$a=2
value of dollar_a is \$b=1
value of dollar_a is \$a=2
value of dollar_a is \$b=3
value of dollar_a is \$a=1
value of dollar_a is \$b=3
value of dollar_a is \$a=2
value of dollar_a is \$b=4
value of dollar_a is \$a=3
value of dollar_a is \$b=4
value of dollar_a is \$a=2
value of dollar_a is \$b=2
value of dollar_a is \$a=2
value of dollar_a is \$b=1
value of dollar_a is \$a=2
value of dollar_a is \$b=1
value of dollar_a is \$a=4
value of dollar_a is \$b=1
value of dollar_a is \$a=3
value of dollar_a is \$b=1
value of dollar_a is \$a=1
value of dollar_a is \$b=1
value of dollar_a is \$a=2
value of dollar_a is \$b=2

It looks that \$a & \$b values correspond to the \$array values. Initially \$a=2 and \$b = 1, i.e., first two values of \$array. \$Key i.e. index of \$order is 0, hence, \$value is 1. Now in the for loop we have :

` if(2 == 1)`

which is false, so we would return 0, where we would go? How the loop is continuing after return?
Surely, it isnât continuing? Itâs just being called repeatedly by `usort` with different parameters. Why not add a few more `echo` statements so you can follow exactly what is happening? Add one after the end of the loop, and see if it displays, for example.