PHP sorting, usort, and the spaceship operator
Sort arrays by value or by custom rules, and combine several sort keys with <=>.
On this page
PHP arrays and closures.
- Sort arrays by value or by custom rules, and combine several sort keys with <=>.
- Predict the sample output and explain the state changes.
- Complete the practice task and check the boundary cases.
The concept
sort and rsort order the values of an array and renumber the keys, while asort, arsort, ksort, and krsort keep the key–value pairs. Since PHP 8.0 the sorts are stable, so equal elements keep their original order. By default strings are compared as strings with capital letters first, so "Fig" sorts before "apple". The flag SORT_FLAG_CASE | SORT_STRING ignores the case.
usort takes a comparison function that returns a negative number, zero, or a positive number. The spaceship operator <=> returns exactly that for numbers and strings. The short ternary a <=> b ?: c falls through to the next key when the first comparison gives zero, which sorts by several keys. usort sorts in place and returns true.
Code example
<?php
$numbers = [5, 2, 9, 1, 5, 6];
sort($numbers);
echo implode(" ", $numbers), "\n";
rsort($numbers);
echo implode(" ", $numbers), "\n";
$people = [["Ada", 30], ["Bo", 25], ["Cy", 30], ["Di", 25]];
usort($people, fn($a, $b) => $a[1] <=> $b[1] ?: strcmp($a[0], $b[0]));
echo implode(",", array_column($people, 0)), "\n";
$words = ["pear", "apple", "Fig"];
sort($words);
echo implode(",", $words), "\n";
sort($words, SORT_FLAG_CASE | SORT_STRING);
echo implode(",", $words), "\n";
$scores = ["Ada" => 90, "Bo" => 85, "Cy" => 90];
arsort($scores);
echo implode(",", array_keys($scores)), "\n";1 2 5 5 6 9 9 6 5 5 2 1 Bo,Di,Ada,Cy Fig,apple,pear apple,Fig,pear Ada,Cy,Bo
Follow the code
Open the walkthrough to inspect the example one step at a time.
Show guided walkthrough
<?php$numbers = [5, 2, 9, 1, 5, 6];sort($numbers);echo implode(" ", $numbers), "\n";rsort($numbers);echo implode(" ", $numbers), "\n"; $people = [["Ada", 30], ["Bo", 25], ["Cy", 30], ["Di", 25]];usort($people, fn($a, $b) => $a[1] <=> $b[1] ?: strcmp($a[0], $b[0]));echo implode(",", array_column($people, 0)), "\n"; $words = ["pear", "apple", "Fig"];sort($words);echo implode(",", $words), "\n";sort($words, SORT_FLAG_CASE | SORT_STRING);echo implode(",", $words), "\n"; $scores = ["Ada" => 90, "Bo" => 85, "Cy" => 90];arsort($scores);echo implode(",", array_keys($scores)), "\n";Follow the example
Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.
View the complete dry-run table
| Step / line | What happens | State after step | Output so far |
|---|---|---|---|
| Ascending order; the array is changed in place. | — | — | |
| Sorted ascending. | — | 1 2 5 5 6 9 | |
| Descending order. | — | 1 2 5 5 6 9 | |
| Compare ages first. If they are equal, <=> gives 0, which is falsy, so ?: falls through to the names. | — | 1 2 5 5 6 9 | |
| Ages 25 first (Bo, Di), then 30 (Ada, Cy), each group alphabetical. | — | 1 2 5 5 6 9 9 6 5 5 2 1 Bo,Di,Ada,Cy | |
| The default string sort puts capital letters first. | — | 1 2 5 5 6 9 9 6 5 5 2 1 Bo,Di,Ada,Cy Fig,apple,pear | |
| The flags ignore case when comparing. | — | 1 2 5 5 6 9 9 6 5 5 2 1 Bo,Di,Ada,Cy Fig,apple,pear | |
| Sort by value, highest first, keeping the keys. The sort is stable, so Ada stays before Cy. | — | 1 2 5 5 6 9 9 6 5 5 2 1 Bo,Di,Ada,Cy Fig,apple,pear | |
| Ada and Cy (90) then Bo (85). | — | 1 2 5 5 6 9 9 6 5 5 2 1 Bo,Di,Ada,Cy Fig,apple,pear apple,Fig,pear Ada,Cy,Bo |
Behind the scenes
How PHP processes this code
The PHP runtime executes the script. echo writes to the response or terminal output.
Cost and common mistakes
O(n log n) for all of these sorts.
- Before PHP 8 the sort functions were not stable. Code that relies on stability must require PHP 8 or later.
- Mixed-type arrays compare in surprising ways. Use the explicit flags SORT_NUMERIC and SORT_STRING.
- usort returns true, not the sorted array. The array you pass in is the one that changes.
Try it yourself
How would you sort the people by age descending?
Reveal answer and reasoning
Swap the operands: usort($people, fn($a, $b) => $b[1] <=> $a[1]);