PHP · Course navigation

PHP sorting, usort, and the spaceship operator

Sort arrays by value or by custom rules, and combine several sort keys with <=>.

On this page
Before you start

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
<?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";
Output
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
Guided walkthroughReady
1<?php
2$numbers = [5, 2, 9, 1, 5, 6];
3sort($numbers);
4echo implode(" ", $numbers), "\n";
5rsort($numbers);
6echo implode(" ", $numbers), "\n";
7
8$people = [["Ada", 30], ["Bo", 25], ["Cy", 30], ["Di", 25]];
9usort($people, fn($a, $b) => $a[1] <=> $b[1] ?: strcmp($a[0], $b[0]));
10echo implode(",", array_column($people, 0)), "\n";
11
12$words = ["pear", "apple", "Fig"];
13sort($words);
14echo implode(",", $words), "\n";
15sort($words, SORT_FLAG_CASE | SORT_STRING);
16echo implode(",", $words), "\n";
17
18$scores = ["Ada" => 90, "Bo" => 85, "Cy" => 90];
19arsort($scores);
20echo 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
Prepared trace of the published program. Some rows group repeated iterations.
Step / lineWhat happensState after stepOutput 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]);

Further reading