Sorting functions in PHP
And the Spaceship Operator 🚀🚀🚀
Found a typo? Edit meWhen 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
sort()
,arsort()
anduasort()
?
Before explaining the repercussions of a
, r
, k
and u
+ sort()
function, we need to know the very basic concept of lists and maps.
List
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 a
, r
, k
& u
+ 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
, 0
and 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 👀