Sorting functions in PHP
And the Spaceship Operator 🚀🚀🚀Found a typo? Edit me
When dealing with PHP, there are multiple ways to sort a collection of items, and sometimes it’s not clear which method we should use and why.
What is the difference between
Before explaining the repercussions of
sort() function, we need to know the very basic concept of lists and maps.
A list is an ordered collection.
The order is sequential starting from 0 and increasing 1 by 1 for each item.
It is also possible to have duplicated items in a list.
$list = ; ; Array
Map (also known as Dictionaries)
A map is an unordered collection.
Each element is composed of a key and a value.
It is not possible to have the same key more than once.
$map = ; ; Array
It was important to do a quick overview of maps and lists, they are different kinds of collections, and because of that, each one has its own specific sorting methods.
The idea of those
sort() is to work as modifiers as follows:
K = key ➝ sort by key, only for maps
A = associative ➝ sort by value, only for maps
U = user-defined ➝ defined by the user in a callback
Sorting Lists 🧵
sort() & rsort()
These methods sort lists in ascending/descending order.
# sort: Sort list by *ascending* order. $sort = ; ; Array --- # rsort: Sort list by *descending* order. $rsort = ; ; Array
Sorting Maps 🗺️
asort(), arsort(), ksort() & krsort()
These methods sort associative arrays by key/value in ascending/descending order.
# ksort: Sort map by *key* in *ascending* order. $ksort = ; ; Array --- # krsort: Sort map by *key* in *descending* order. $krsort = ; ; Array --- # asort: Sort map by *value* in *ascending* order. $asort = ; ; Array --- # arsort: Sort map by *value* in *descending* order. $arsort = ; ; Array
User-defined functions 👩💻
Until now everything was nice, but as you know, usually we have a collection of complex objects, and sometimes we want to define our own sorting function, in these scenarios, the asort() method simply doesn't work. Eg:
“Sorting a collection of
Product by price in ascending order, and when more than one product has the same price, sort
them alphabetically by the name”.
We need to find a more sophisticated approach. And this is only possible if we can define our own sorting method, in
this case, we can take advantage of using the
spaceship operator! 🚀
Basically, this operator is syntactic sugar specialized for comparisons.
The first parameter is the array we want to sort and the second is a callback that returns an integer value.
/** @var callable(mixed,mixed):int $callable */ $callable = : bool
The values this callable must return are
1 if the current item is less, equal or greater than the
previous one, to be sorted before or after in the collection.
# Is the same than... # Is the same than... int $a, int $b)=> $a <=> $b;
usort(), uksort() & uasort()
These methods sort by keys or values (preserving or resetting the keys) in a user-defined callback. Let’s see some examples:
# usort: Sort list/map by callback from the values, keys are reset. $usort = ; ; Array --- # uksort: Sort map by callback from the keys. $uksort = ; ; Array --- # uasort: Sort map by callback from the values preserving the keys. $uasort = ; ; Array
For the sake of simplicity, I used the function:
fn ($a, $b) => $a <=> $b; if the collection was holding complex
objects, it would be the same but comparing some property, it depends on your needs.
📑 Cheat Sheet
- sort list in ascending order - sort list in descending order - sort map by value in ascending order - sort map by key in ascending order - sort map by value in descending order - sort map by key in descending order - sort list or map by value in a user-defined callback, reset keys - sort map by keys in a user-defined callback - sort map by value in a user-defined callback
* Take into account that the array is passed by reference to the sorting function, which means you must initialize the array in a different line, and the sorting function will mutate the original array 👀