## Introduction

Arrays are one of the most fundamental types of data in programming. And one of the most fundamental operations performed on arrays is that of ** sorting**.

Sorting is essentially to reorder elements of a given array such that they either line up in ascending (increasing) order or in descending (decreasing) order.

In this chapter, we shall explore how to sort arrays in PHP. In particular, we'll be looking at the three different categories of functions, i.e ones that sort by values (`sort()`

, `rsort()`

, `usort()`

); ones that sort by keys (`ksort()`

, `krsort()`

, `uksort()`

); and ones that sort by values but keeping the keys in tact (`asort()`

, `arsort()`

, `uasort()`

).

## Different kinds of sorting

If we look up the official documentation of PHP, we see that there is a large collection of functions meant to sort arrays.

To be precise, we have ** sort()**,

**and**

`rsort()`

**;**

`usort()`

**,**

`ksort()`

**and**

`krsort()`

**;**

`uksort()`

**,**

`asort()`

**and**

`arsort()`

**.**

`uasort()`

If this wasn't enough, we also have ** natsort()** and

**.**

`natcasesort()`

Now some questions that immediately arise in the mind upon looking at this are: *What's the point of so many sorting functions?* *What's asort() for?*

*How's*

`uksort()`

different from `ksort()`

?*What's*

`krsort()`

then?Well, contrary to how it seems, the answers to all of these questions are actually really simple. But first we need to clarify the main distinction between them.

### Sorting by values

To start with, we have ** sort()** and

**— the most basic functions. Both of them sort**

`rsort()`

*by values*which simply means that they look at the values of a given array while sorting it, not its keys.

`sort()`

sorts an array in ascending order (of values). On the other hand, `rsort()`

is just the reverse of `sort()`

, i.e. it reorders the elements in descending order.

`sort()`

(and `rsort()`

and `usort()`

) is typically used on indexed arrays where the key-value association doesn't really matter to us. That is, it doesn't matter whether the first element (with the key `0`

) becomes, let's say, the second element (with the key `1`

).

There is yet another function in this sort-by-value category and that is ** usort()**.

`usort()`

is related to `sort()`

in that it also sorts by values (where the keys aren't preserved), but this time we manually provide a comparison function to it.

If you don't understand what *'sort by values'* means here, don't worry at all — we'll be presenting examples below of each of these functions which'll hopefully clarify any confusion that you might have at this stage.

### Sorting by keys

Next up, we have ** ksort()**,

**and**

`krsort()`

**.**

`uksort()`

Before we even explain the purpose of these functions, notice a pattern here: we have the names *'sort'* and *'rsort'* again and even a name with *'u'* at its beginning. *Hmm. This is interesting.*

The name *'sort'* essentially implies sorting in ascending order; *'rsort'* implies sorting in descending order (which is just reverse ascending order); and *'u'* implies sorting based on a user-defined comparison function.

*But then what does the letter 'k' represent here?* Well, *'k'* stands for *'key'*.

Likewise, ** ksort()** sorts an array in ascending order of its keys. Similarly,

**does the reverse of**

`krsort()`

`ksort()`

, i.e. it sorts the array in descending order of its keys.`ksort()`

is, as you can probably guess, used on associative arrays where we want the ordering to be governed by the keys of the arrays.

And then just like we have `usort()`

akin to `sort()`

, we have ** uksort()** akin to

`ksort()`

. That is, `uksort()`

behaves like `ksort()`

, just that the comparisons in the sorting routine are based on a user-defined function.### Sorting by values, with key preservations

Last up, we have ** asort()**,

**and**

`arsort()`

**.**

`uasort()`

Recall the nomenclature pattern from the previous section? It's in action here as well.

We can make an educated guess that `asort()`

would sort in ascending order of *'something'*, `arsort()`

would sort in descending order of that *'something'*, and `uasort()`

would showcase a similar behavior, sorting in terms of that *'something,'* albeit with a user-defined comparison function.

*So now, what's the 'a' for?*

The *'a'* here stands for *'association'* and means that the key-value associations are retained in these sorting functions. To be precise, all of these three functions sort an array by values, but also keep the keys intact, unlike the first category of functions that we saw above.

** asort()** sorts an array in ascending order of its values, with keys preserved.

**is simply the reverse of**

`arsort()`

`asort()`

.Finally, ** uasort()** is just

`asort()`

with a user-defined comparison function.## How are arrays sorted in PHP?

Before anything can begin, one has to choose a given sorting algorithm that handles almost the entire logic of sorting; the rest logic being handled by the comparison function.

As a matter of fact, PHP uses an implementation of the ** Quicksort** algorithm. The exact details of the algorithm are beyond the scope of this chapter.

The second most important thing after the sorting algorithm is the comparison function.

If you've ever worked with sorting algorithms before, or at least have tried solving the PHP Control Flow — Selection Sort Exercise in this course, you'd know that sorting is all about **comparisons**.

Different items in a given array, which is meant to be sorted, are compared to one another in order to determine which one should come first, which one second, and so on. Comparison is an integral part of sorting.

Now all sorting functions in PHP, except for `usort()`

, `uksort()`

and `uasort()`

, rely on predefined comparison functions.

These comparison functions essentially take two values, * a* and

*, that are meant to be compared, and then return either*

`b`

`-1`

, `0`

or `1`

, to specify which of those two values should come first.The rules are really simple:

`-1`

means thatshould come before`a`

.`b`

`0`

means thatshould remain in its original order relative to`a`

.`b`

`1`

means thatshould come before`b`

.`a`

This integer returning approach is not unique to PHP; it's conventional and employed in many other programming languages as well, including JavaScript.

For instance, the comparison function used by `sort()`

returns `-1`

when * a* is less than

*, so*

`b`

*comes first. On the same lines, the comparison function used by*

`a`

`rsort()`

returns `-1`

when *is greater than*

`a`

*, so that*

`b`

*comes first.*

`a`

All sorting functions in PHP that are based on predefined comparison functions provide us with a second parameter that can be leveraged to configure the underlying comparison function. If we don't specify any configuration — that is, any argument to the second parameter — a function that is based on the default comparison behavior is used.

And the default comparison behavior is to perform a ** regular** comparison of the two given values.

A regular comparison is basically just `<`

, `>`

and `==`

, followed by returning an integer based on the relation between the values and the sorting function being used.

The reason we call it *'regular'* is perhaps because it's the regular, i.e. the normal, way of comparing two values in PHP.

#### Regular comparison semantics

The official documentation provides us with all the necessary information to understand how *exactly* values are compared in PHP when using `<`

, `>`

or `==`

.

Shown below is the sequence of steps used when comparing two arbitrary values, * a* and

*, for either of the relations*

`b`

`<`

, `>`

or `==`

:Type of `a` | Type of `b` | Type juggling | Comparison |
---|---|---|---|

String or `NULL` | String | Both the values are coerced into strings. | Numerical comparison if the both the strings are numeric strings, or else lexical comparison. |

Boolean or `NULL` | Anything | Both the values are coerced into Booleans. | Normal comparison of Booleans, where `false < true` . |

Object | Object | - | Normal comparison of objects. |

String, resource, int or float | String, resource, int or float | Both the operands are coerced into numbers. | Numerical comparison. (It's just basic math!) |

Object | Anything | - | Object is greater. |

Array | Anything | - | Array is greater. |

This sequence of steps might seem intimidating, and rightly so.

Fortunately, the good news is that you're not required to remember this; in fact, given that you always make sure that an array has elements of the same type, you won't even need to consult it!

It's just a well-defined algorithm that PHP uses to compare any two arbitrary values together using the `<`

, `>`

and `==`

operators.

You might have noticed the word *'lexical'* above. Lexical comparison refers to the standard way comparing two strings with one another to determine whether they are equal or not, and if not, then which one is lexically smaller and which one lexically larger.

The next snippet explains how lexical comparison happens.

#### How lexical comparison happens?

Iteration is performed over both the given strings simultaneously, comparing corresponding code units with one another.

If at any point a mismatch is found, the string with the code unit whose value is greater than the corresponding code unit in the other string is termed as ** lexically larger** than that string; accordingly, the other string is termed as

**.**

*lexically smaller*However, if no mismatch is found until either one of the strings has been exhausted by the iterations (i.e. its end reached), then at that point there are two possibilities:

- The length of both the strings is the same. In that case, the string are exactly identical to one another.
- The length of both the strings is NOT the same. In that case, the string with a larger length is lexicographically larger than the other one; accordingly, the other string is the lexicographically smaller one.

For example, in `sort()`

, the comparison function will return `-1`

if

. But in *a* < *b*`rsort()`

, the comparison function will return `1`

if

, because in that case *a* < *b** b* ought to be placed before

*.*

`a`

At this point, it's worthwhile mentioning that if two values being compared are found to be equal to one another, then their original relative order is preserved in the sorted array. In the language of sorting algorithms, this feature makes the sorting algorithm be termed as ** stable**.

Stable sorting means that if two values are equal to one another in an array, their original order would remain preserved in the sorted array.

`sort()`

and `rsort()`

Let's now start exploring the sorting functions individually, in detail, starting with the first kind, i.e. functions sorting by values (without retaining keys).

We have ** sort()** and

**to consider here.**

`rsort()`

**will be considered in a separate section along with**

`usort()`

`uksort()`

and `uasort()`

.Here's the syntax of `sort()`

:

**sort**(&*$array*, *$flags* = SORT_REGULAR)

The first argument is the array to sort. Recall that `&`

implies that * $array* is a reference parameter, i.e. it refers to the original array provided.

The second * $flags* argument configures the logic of the comparison function used internally. We'll explore this second argument later on below.

Let's consider a couple of examples now.

Let's say we have the following array of numbers and wish to sort them in ascending order, which is perhaps the most basic of wishes from the perspective of sorting:

```
<?php
$nums = [10, -5, 0, 0.7, 10, -7.8, 33];
```

Time to get it done using `sort()`

:

```
<?php
$nums = [10, -5, 0, 0.7, 10, -7.8, 33];
sort($nums);
```

And we're done.

Let's confirm the result using `print_r()`

:

```
<?php
$nums = [10, -5, 0, 0.7, 10, -7.8, 33];
sort($nums);
print_r($nums);
```

Yup, we have exactly what we expected.

Now suppose we have to sort these numbers in descending order.

Once again, no problem; just use `rsort()`

:

```
<?php
$nums = [10, -5, 0, 0.7, 10, -7.8, 33];
rsort($nums);
print_r($nums);
```

*Simple, isn't this?*

As another example, suppose we have to sort the following list of programming languages in descending order:

```
<?php
$langs = ['PHP', 'JavaScript', 'C', 'Ada', 'Bash', 'C#', 'Go', 'Ruby'];
```

`rsort()`

, over to you:

```
<?php
$langs = ['PHP', 'JavaScript', 'C', 'Ada', 'Bash', 'C#', 'Go', 'Ruby'];
rsort($langs);
print_r($langs);
```

And we're done.

If you've worked with JavaScript, you'll know that there is additional code required if we wish to sort an array of numbers vs. if we wish to sort an array of strings (which doesn't require any code). This is by virtue of the fact that JavaScript sorts elements lexically by default.

In PHP, though, we don't need to worry about whether we have an array of numbers or an array of strings (as long as all the elements are of the same type); the default *'regular'* comparison logic abstracts away this from us.

Let's see what happens when we have an array of numbers and stringified numbers (strings containing numeric values) and then sort it using `sort()`

:

```
<?php
$arr = [10, '-5', '50', 0.7, 10, '-7.8', 33];
sort($arr);
print_r($arr);
```

*Surprised or not by the output?*

Well there should be some element of surprise since `sort()`

seems to have performed really intelligently here — it didn't group the strings at one end and the numbers at the other; instead it figured out that the strings are numeric strings and, likewise, compared them with numbers after having coerced them into numbers as well.

For instance, if `10`

and `'-7.8'`

were compared in the sorting routine, first `'-0.7'`

would've been converted into a number to give `-7.8`

, and then this number would've been compared with `10`

.

`ksort()`

and `krsort()`

In order to sort an array based on its **keys**, we use ** ksort()** and

**.**

`krsort()`

`ksort()`

sorts an array in ascending order of keys. Here's its syntax:

**ksort**(&*$array*, *$flags* = SORT_REGULAR)

On the same lines, `krsort()`

sorts an array in descending order of keys.

`ksort()`

(and `krsort()`

) is typically meant to be used on associative arrays, not indexed arrays (because the keys there, i.e. 0, 1, 2, ..., are already sorted), where we want to base the sorting upon keys.

Let's consider an example. Shown below we have an associative array depicting the count of given words in a scanned piece of arbitrary text:

```
<?php
$word_counts = [
'us' => 21,
'great' => 5,
'simple' => 1,
'cats' => 30,
'cute' => 10,
'original' => 10,
];
```

We want to showcase the words, along with their counts, in ascending order. Note that the words must be in ascending order, not their counts.

Now since this task is concerned with the keys of `$word_counts`

, what we need is `ksort()`

:

```
<?php
$word_counts = [
'us' => 21,
'great' => 5,
'simple' => 1,
'cats' => 30,
'cute' => 10,
'original' => 10,
];
ksort($word_counts);
print_r($word_counts);
```

*Voila!* The words have been lined up in ascending order.

Let's also demonstrate `krsort()`

with the same `$word_counts`

array:

```
<?php
$word_counts = [
'us' => 21,
'great' => 5,
'simple' => 1,
'cats' => 30,
'cute' => 10,
'original' => 10,
];
krsort($word_counts);
print_r($word_counts);
```

*Perfect*; all the words sorted in descending order.

`asort()`

and `arsort()`

Akin to `sort()`

, ** asort()** sorts an array based on its values, but this time the keys are kept intact unlike in

`sort()`

.In particular, `asort()`

sorts an array in ascending order of values while ** arsort()** sorts it in descending order of values, whereby they key bindings remain preserved.

Syntactically, the functions are identical to `sort()`

and `ksort()`

:

**asort**(&*$array*, *$flags* = SORT_REGULAR)

Time for an example.

Let's say we want to sort the `$word_counts`

array shown above based on the counts of words, not the word themselves.

Clearly, using `sort()`

won't be helpful in this case, as demonstrated below:

```
<?php
$word_counts = [
'us' => 21,
'great' => 5,
'simple' => 1,
'cats' => 30,
'cute' => 10,
'original' => 10,
];
// sort() ain't gonna be helpful!
sort($word_counts);
print_r($word_counts);
```

Even though the counts indeed line up in ascending order, we've lost their association to given words.

What we need instead is `asort()`

, to keep the key-value association intact:

```
<?php
$word_counts = [
'us' => 21,
'great' => 5,
'simple' => 1,
'cats' => 30,
'cute' => 10,
'original' => 10,
];
asort($word_counts);
print_r($word_counts);
```

See how the words are lined up in ascending order of their counts, with the words kept intact. *Perfect!*

As before, let's also consider the reverse function `arsort()`

:

```
<?php
$word_counts = [
'us' => 21,
'great' => 5,
'simple' => 1,
'cats' => 30,
'cute' => 10,
'original' => 10,
];
arsort($word_counts);
print_r($word_counts);
```

*Simple and elegant.*

## Sorting constants

With the exception of `usort()`

, `uksort()`

and `uasort()`

, the syntax of all the sorting functions shown above is the exact same. That is, the first argument is the array to sort (which is passed in by reference) while the second argument is a set of constants specifying the nature of the comparisons.

Basically, the second argument is a means of customizing the comparison function with given presets.

Here's a list of all the constants that can be provided in as the second argument to configure the comparison function:

Constant | Description |
---|---|

`SORT_REGULAR` | The comparisons are regular, i.e. using the same routine used internally by the `<=>` operator. |

`SORT_NUMERIC` | When comparing two elements with one another, they are first coerced into numbers and then numerical comparison is performed. |

`SORT_STRING` | When comparing two elements with one another, they are first coerced into strings and then lexical comparison is performed. |

`SORT_LOCALE_STRING` | Same as `SORT_STRING` but based on the current locale. |

`SORT_NATURAL` | Almost same as `SORT_STRING` except for that it uses natural comparisons instead of strictly lexical comparisons. |

`SORT_FLAG_CASE` | An additional flag that could blended in with `SORT_STRING` and `SORT_NATURAL` to make the comparisons case-insensitive. |

`SORT_REGULAR`

First in line we have ** SORT_REGULAR**.

This refers to the *'regular'* comparison semantics, i.e. the one performed by the spaceship (`<=>`

) operator. Type juggling is obviously in action in this kind of comparison. We've already explored how these regular comparisons work in the previous sections.

`SORT_NUMERIC`

Next, we have ** SORT_NUMERIC**.

As the name suggests, `SORT_NUMERIC`

performs numerical comparisons and that by converting each element to a number before comparison. This leads to pretty surprising, albeit easy to reason about, results.

Consider the following code:

```
<?php
$arr = [-1, 'us', 0, 'is', 'as'];
sort($arr, SORT_NUMERIC);
print_r($arr);
```

We have a mixture of different kinds of elements in `$arr`

and want to see the result when it's sorted using the `SORT_NUMERIC`

flag set:

We obviously know that `'as'`

comes before `'is'`

, and `'is'`

comes before `'us'`

, yet in the sorted array above, that's not the case. Each of these three strings remains in their original relative orders, thanks to the fact that they all coerce to the same number `0`

and that `sort()`

does stable sorting.

The fact that all the strings coerce to `0`

can be further confirmed by the fact that in the sorted array, `-1`

comes first, followed by the strings, followed by `1`

.

`SORT_STRING`

Let's now move to the third kind that is ** SORT_STRING**.

Just like `SORT_NUMERIC`

, `SORT_STRING`

is very easy to make sense of. It means that the comparisons are all made in terms of strings — or better to say, the comparisons are ** lexical**.

In `SORT_STRING`

, when comparing two elements, they both are converted into strings and then the `strcmp()`

function is used to perform the comparison.

*always*lexical in the case of

`SORT_STRING`

, even though when numbers are coerced into strings, they becomes numeric strings, which are otherwise compared numerically in PHP.Shown below is an example:

```
<?php
$arr = [20, 3, 25, 100];
sort($arr, SORT_STRING);
print_r($arr);
```

Without `SORT_STRING`

, we expect the result to be as follows: `3`

, `20`

, `25`

, `100`

, as `sort()`

sorts in ascending order. But with the `SORT_STRING`

flag set, there's a significant difference:

The reason is simple: the first character of `'100'`

is lexically smaller than the first character of `'20'`

, `'25'`

and `'3'`

, likewise it is lexically smaller than all of the given strings. A similar idea applies to `'20'`

, `'25'`

and `'3'`

.

`SORT_NATURAL`

Let's now talk about ** SORT_NATURAL**.

As stated above, `SORT_NATURAL`

works pretty much like `SORT_STRING`

in that it also converts each element to a string before comparison.

However, it uses what's called a *'natural comparison algorithm'* whereby sequences of digits are treated how we'd otherwise treat them naturally; they are NOT treated lexically.

For example, lexically `'a50'`

is smaller than `'a6'`

(because of the comparison of the corresponding characters `5`

and `6`

), however naturally, `'a50'`

is larger than `'a6'`

, as `50`

is naturally a larger number as compared to `6`

.

Let's see `SORT_NATURAL`

in action on the same array of four numbers shown above:

```
<?php
$arr = [20, 3, 25, 100];
sort($arr, SORT_NATURAL);
print_r($arr);
```

*And there's the difference.*

`SORT_FLAG_CASE`

Last but not the least, we have the flag ** SORT_FLAG_CASE**.

`SORT_FLAG_CASE`

is basically just an additional flag that we can blend in with either `SORT_STRING`

or `SORT_NATURAL`

in order to make the string comparison case-insensitive. The blending is done via the bitwise OR (`|`

) operator.

What `SORT_FLAG_CASE`

does internally is that when two strings are compared, they are first converted into lower case and then the comparison is performed.

Consider the following example:

```
<?php
$technologies = ['php', 'Python', 'ada', 'JavaScript', 'jQuery', 'jest'];
sort($technologies);
print_r($technologies);
```

Here we have an array of strings, some starting with lowercase letters while some starting with uppercase letters.

When we sort it, the strings starting with uppercase letters are grouped together and then we have all the strings starting with lowercase letters. And obviously each group itself is sorted.

Now the reason the uppercase strings come first is because the uppercase alphabet comes before the lowercase alphabet lexically. (The code unit of `A`

is `65`

while the code unit of `a`

is `97`

.)

Anyways, now let's make the comparison case-insensitive using `SORT_STRING`

blended together with `SORT_FLAG_CASE`

:

```
<?php
$technologies = ['php', 'Python', 'ada', 'JavaScript', 'jQuery', 'jest'];
sort($technologies, SORT_STRING | SORT_FLAG_CASE);
print_r($technologies);
```

Witness the sorted array here — the strings are now grouped according to their first letters regardless of the casing of those letters. We have `'ada'`

right at the start because `a`

comes first, while `'Python'`

at the end because `'p'`

(in lowercase) comes last here.

Just as shown in this example, `SORT_FLAG_CASE`

is really handy when we need to sort an array of strings where we know that the strings would have different casings.

## User-defined sorting

There are three sorting functions in PHP that work with **user-defined comparison functions** instead of relying on built-in comparison functions. They are ** usort()**,

**and**

`uksort()`

**.**

`uasort()`

Recall that the *'u'* here stands for *'user-defined'* which signifies the fact that each of these functions operates around a user-defined comparison function.

These sorting functions are handy when our arrays are comprised of elements whose comparison does not happen the way we intend it to happen; in that case, our own custom comparison function comes to the rescue.

Here's the syntax of `usort()`

, which is the same as that of `uksort()`

and `uasort()`

:

**usort**(&*$array*, *$comparison_fx*)

The first argument is the array to sort while the second argument is the function to use when comparing two elements of the array in the sorting routine.

As the sorting routine progresses, it invokes the given comparison function on different pairs of elements to determine which one should come before the other.

In this regard, the comparison function receives the elements as two arguments, let's call them `$a`

and `$b`

. It's meant to return either `-1`

, `0`

, or `1`

, to help the sorting routine determine which of the two elements should come first.

Here's how these return values work:

`-1`

if`$a`

is less than`$b`

, i.e.`$a`

should come*before*`$b`

.`0`

if`$a`

is equal to`$b`

.`1`

if`$a`

is greater than`$b`

, i.e.`$a`

should come*after*`$b`

.

Let's consider an example.

Suppose we have the following array where each element represents a point on a Cartesian plane:

```
<?php
$points = [ [0, 1], [1, 0], [3, 9], [-5, 9], [-1, -1], [-9, -27] ];
```

Our job is to sort the array based on the distances of each point from the origin, in ascending order.

Obviously, because computing the distance requires a bit of processing, we need a configurable sorting function — `usort()`

to be precise.

First, let's define the comparison function:

```
<?php
function compare_distances($p1, $p2) {
$dist1 = ($p1[0] ** 2 + $p1[1] ** 2) ** 0.5;
$dist2 = ($p2[0] ** 2 + $p2[1] ** 2) ** 0.5;
return $dist1 <=> $dist2;
}
```

`$p1`

and `$p2`

represent two different points in the `$points`

array. We compute the distances of both of them from the origin and then perform regular comparison of the resulting distances (which are numbers) via the spaceship (`<=>`

) operator.

Now, let's make the call to `usort()`

providing in our function's name as the second argument:

```
<?php
function compare_distances($p1, $p2) {
$dist1 = ($p1[0] ** 2 + $p1[1] ** 2) ** 0.5;
$dist2 = ($p2[0] ** 2 + $p2[1] ** 2) ** 0.5;
return $dist1 <=> $dist2;
}
$points = [ [0, 1], [1, 0], [3, 9], [-5, 9], [-1, -1], [-9, -27] ];
usort($points, 'compare_distances');
```

As we shall learn in the PHP Functions unit, if PHP expects a function as an argument, we can provide it a string denoting the name of a global function; it's not possible to pass a global function directly.

Now, let's see the ordering of elements in the `$points`

array by outputting it. Owing to the fact that `print_r()`

would make the output quite verbose in this case, we'll spin up a `foreach`

loop to output all of the individual points, along with their distances from the origin.

Here's the final code:

```
<?php
function compare_distances($p1, $p2) {
$dist1 = ($p1[0] ** 2 + $p1[1] ** 2) ** 0.5;
$dist2 = ($p2[0] ** 2 + $p2[1] ** 2) ** 0.5;
return $dist1 <=> $dist2;
}
$points = [ [0, 1], [1, 0], [3, 9], [-5, 9], [-1, -1], [-9, -27] ];
usort($points, 'compare_distances');
foreach ($points as $point) {
$distance = ($point[0] ** 2 + $point[1] ** 2) ** 0.5;
printf("(%d, %d), distance: %.2f\n", $point[0], $point[1], $distance);
}
```

Let's run it and see the output produced:

*And there you have it!* The points have been lined up in increasing order of their distances from the origin.

If we wish to sort the points in decreasing order of their distances, we can simply negate the output of the spaceship (`<=>`

) operator, using the arithmetic negation (`-`

) operator, in the function `compare_distances()`

, as follows.

Let's try doing so:

```
<?php
function compare_distances($p1, $p2) {
$dist1 = ($p1[0] ** 2 + $p1[1] ** 2) ** 0.5;
$dist2 = ($p2[0] ** 2 + $p2[1] ** 2) ** 0.5;
// This time we want the points in descending order.
return -($dist1 <=> $dist2);
}
$points = [ [0, 1], [1, 0], [3, 9], [-5, 9], [-1, -1], [-9, -27] ];
usort($points, 'compare_distances');
foreach ($points as $point) {
$distance = ($point[0] ** 2 + $point[1] ** 2) ** 0.5;
printf("(%d, %d), distance: %.2f\n", $point[0], $point[1], $distance);
}
```

As you can see, the points are now lined up in decreasing order. *Amazing!*

Another way to accomplish this exact same thing is to swap the operands of the spaceship operator in `compare_distances()`

, as follows:

```
<?php
function compare_distances($p1, $p2) {
$dist1 = ($p1[0] ** 2 + $p1[1] ** 2) ** 0.5;
$dist2 = ($p2[0] ** 2 + $p2[1] ** 2) ** 0.5;
// Negating is the same as swapping the order of operands.
return $dist2 <=> $dist1;
}
...
```

*So what do you say? Isn't this easy?*

`[0, 1]`

always comes before `[1, 0]`

. This is because the distances of both these points are the exact same, and then since all sorting functions in PHP are *stable*, the relative order of these two points remains the same as in the initial array.