How to Sort Arrays in PHP
Sorting makes many tasks that require accessing or obtaining a specific set of data very easy and efficient. In this tutorial, we will learn how to use the built-in PHP functions to sort various types of arrays.
Sorting Arrays by Value
Sorting an array by the value of its elements is very easy in PHP. You can choose to keep or discard key-value associations, and you can also define your own functions to define how the elements are sorted. I’ll show you how in this part of the tutorial.
You can use the sort(&$array, $sort_flags) function to sort the array values from low to high. However, it will not maintain key-value associations when sorting the array. New keys are assigned to sorted elements instead of a simple rearrangement. An optional second parameter lets you specify how the elements should be ordered. It can have six different values:
- SORT_REGULAR — This will sort the values without changing their type.
- SORT_NUMERIC — This will sort the values by comparing them numerically.
- SORT_STRING — This will sort the values by comparing them as strings.
- SORT_LOCALE_STRING — This will compare values as strings based on the current locale. You can update the locale yourself by using setlocale().
- SORT_NATURAL — This will sort the items using “natural ordering” while comparing them as strings.
- SORT_FLAG_CASE — This can be combined with SORT_STRING or
- SORT_NATURAL to turn off case sensitivity while sorting strings.
Here are some sorting examples to help you quickly understand the difference between all sort flags.
<?php
$random_data = [32508, 98134, "234984", "3249832", "38", 123, "Apple"];
sort($random_data);
echo "Regular Sorting — ";
foreach($random_data as $element) {
echo str_pad($element, 9)." ";
}
// Regular Sorting — 38 123 32508 98134 234984 3249832 Apple
sort($random_data, SORT_NUMERIC);
echo "\nNumeric Sorting — ";
foreach($random_data as $element) {
echo str_pad($element, 9)." ";
}
// Numeric Sorting — Apple 38 123 32508 98134 234984 3249832
sort($random_data, SORT_STRING);
echo "\nString Sorting — ";
foreach($random_data as $element) {
echo str_pad($element, 9)." ";
}
// String Sorting — 123 234984 3249832 32508 38 98134 Apple
In the example, regular sort, the numeric string is converted to its numeric value and the sort is performed accordingly. The string “Apple” is non-numeric so it is untouched and compared as a string.
In the second example, numerical sorting, we want the data to be sorted by numeric values so that “Apple” is converted to the numeric value 0 and above. The rest of the values are sorted as expected.
In the third example, all values are treated as strings. This means that instead of comparing the numeric value 123 or 3249832 with 38, it is compared as a string — one character at a time. Since “1” comes before “3”, the value 123 is considered lower than 38.
If you want to sort your array values from high to low instead of low to high, you can do so with the help of the rsort() function. It accepts all the same parameters as sort() but sorts the values in reverse order. It also doesn’t maintain key-value associations, so it’s not a good choice for sorting associative arrays.
Sort Array Associative
Key value associations become important when you are dealing with Associative arrays. Consider the following example where the Associative array is used to store the names of different people and their favorite fruit. If you want to sort the list alphabetically by fruit name, using the sort() function from the previous section will result in the loss of associated keys.
<?php
$fruit_preferences = ["James" => "Orange", "John" => "Banana", "Patricia" => "Apple", "Jennifer" => "Mango", "Mary" => "Grapes"];
echo "Before Sorting — \n";
foreach($fruit_preferences as $person=>$preference) {
echo $person." likes ".$preference."\n";
}
/*
Before Sorting —
James likes Orange
John likes Banana
Patricia likes Apple
Jennifer likes Mango
Mary likes Grapes
*/
sort($fruit_preferences);
echo "After Sorting — \n";
foreach($fruit_preferences as $person=>$preference) {
echo $person." likes ".$preference."\n";
}
/*
After Sorting —
0 likes Apple
1 likes Banana
2 likes Grapes
3 likes Mango
4 likes Orange
*/
?>
As you can see, not only do we lose people’s association with their favorite fruit, we also lose the names of different people. Each sorted value has been assigned a new numeric index based on its position in the sorted array.
To help you solve this problem easily, PHP has two different functions that maintain a key-value association while sorting the array by value. These two functions are asort() and arsort(). The following code snippet sorts the same $fruit_preferences array but uses asort() to do so.
<?php
$fruit_preferences = ["James" => "Orange", "John" => "Banana", "Patricia" => "Apple", "Jennifer" => "Mango", "Mary" => "Grapes"];
echo "Before Sorting — \n";
foreach($fruit_preferences as $person=>$preference) {
echo $person." likes ".$preference."\n";
}
/*
Before Sorting —
James likes Orange
John likes Banana
Patricia likes Apple
Jennifer likes Mango
Mary likes Grapes
*/
asort($fruit_preferences);
echo "After Sorting — \n";
foreach($fruit_preferences as $person=>$preference) {
echo $person." likes ".$preference."\n";
}
/*
After Sorting —
Patricia likes Apple
John likes Banana
Mary likes Grapes
Jennifer likes Mango
James likes Orange
*/
?>
As is evident from the example above, Apple’s value is moving upwards while still maintaining its relationship with Patricia. Fruit names can be sorted in reverse easily using the arsort() function.
These two functions accept the same sort flag with the values of their optional second parameters as sort() and rsort().
Sort Array Elements by Value with User Defined Function
The four sorting functions can easily handle your general sorting needs with the help of various flags. However, sometimes your criteria for comparing array elements may be different.
Say you have an array of random words that need to be sorted alphabetically. However, you’ll also want to sort them by length before sorting them alphabetically. For example, zoo will appear after apple in traditional alphabetical sorting. However, if you want to show short words before longer ones, zoo will appear before apple. In the same set of letters, ape will come before zoo because of the alphabetical order.
Basically, words are sorted first by length and then words with the same number of letters are sorted alphabetically in their own group. This sorting type is not built into PHP so we have to write our own sorting function.
What PHP does in this case is it gives you some functions that can be used to pass the array you want to sort along with the name of your own sorting function.
You can use the usort() function to sort array values in a regular array. Similarly, you can use the uasort() function to sort values in an associative array while also maintaining key-value associations.
The code snippet below shows one way to accomplish this behavior.
<?php
$random_words = ["ape", "apple", "zoo", "pie", "elephant", "banana", "picnic", "eye"];
sort($random_words);
echo "Regular Sort Function: \n";
foreach($random_words as $element) {
echo str_pad($element, 9)." ";
}
/*
Regular Sort Function:
ape apple banana elephant eye picnic pie zoo
*/
function custom_sort($word_a, $word_b) {
if (strlen($word_a) < strlen($word_b)) {
return -1;
}
if (strlen($word_a) == strlen($word_b)) {
return strcmp($word_a, $word_b);
}
if (strlen($word_a) > strlen($word_b)) {
return 1;
}
}
usort($random_words, "custom_sort");
echo "\nCustom Sort Function: \n";
foreach($random_words as $element) {
echo str_pad($element, 9)." ";
}
/*
Custom Sort Function:
ape eye pie zoo apple banana picnic elephant
*/
?>
In a callback function intended for custom sorting, we must return an integer less than 0 to indicate that the first value is less than the second. Returns 0 if the first value is equal to the second. Return an integer greater than 0 if the first value is greater than the second.
Since our primary sorting criterion is string length, we immediately return -1 if the first word is shorter than the second. Similarly, we immediately return 1 if the first word is longer than the second. If the two words are the same length, we compare them alphabetically using the strcmp() function and return the values.
As you can see in the output, our custom sort function rearranges the words exactly the way we want.
Array Sorting by key
Sorting an array by key is generally useful when you’re dealing with associative arrays. For example, you might have an array with information about the number of airports in different countries. Assuming that the different country names are keys and the number of airports is a value/array, you may want to sort the country names alphabetically. This is very easy to do with the ksort() and krsort() functions. These two functions will maintain the key-value association of the array elements after sorting. The ksort() function sorts keys from low to high and krsort() sorts keys from high to low.
Here’s an example of basic sorting:
<?php
$airport_count = ["United States" => 13513, "Brazil" => 4093, "Mexico" => 1714, "Canada" => 1467, "Russia" => 1218, "Argentina" => 1138, "Bolivia" => 855, "Colombia" => 836, "Paraguay" => 799, "Indonesia" => 673];
ksort($airport_count);
foreach($airport_count as $country=>$count) {
echo str_pad($country, 15)." ".$count."\n";
}
/*
Argentina 1138
Bolivia 855
Brazil 4093
Canada 1467
Colombia 836
Indonesia 673
Mexico 1714
Paraguay 799
Russia 1218
United States 13513
*/
?>
You can also provide PHP without your own custom function to sort the array of keys using the uksort() function. Just like usort(), the callback function in uksort() also requires that you return an integer less than 0 if the first key is considered less than the second and an integer greater than 0 if the first key is greater than the second. This function also maintains the key-value association of array elements.
<?php
$airport_count = ["United States" => 13513, "Brazil" => 4093, "Mexico" => 1714, "Canada" => 1467, "Russia" => 1218, "Argentina" => 1138, "Bolivia" => 855, "Colombia" => 836, "Paraguay" => 799, "Indonesia" => 673];
function custom_sort($word_a, $word_b) {
if (strlen($word_a) < strlen($word_b)) {
return -1;
}
if (strlen($word_a) == strlen($word_b)) {
return strcmp($word_a, $word_b);
}
if (strlen($word_a) > strlen($word_b)) {
return 1;
}
}
uksort($airport_count, "custom_sort");
foreach($airport_count as $country=>$count) {
echo str_pad($country, 15)." ".$count."\n";
}
/*
Brazil 4093
Canada 1467
Mexico 1714
Russia 1218
Bolivia 855
Colombia 836
Paraguay 799
Argentina 1138
Indonesia 673
United States 13513
*/
?>
In the above example, we have used the custom sort function from the previous section to sort country names first by the length of their names and then alphabetically.
Sorting Multi-Dimensional Arrays in PHP
It is much more common in real life to deal with multi-dimensional information. For example, an institution will store the grades of all students in various subjects in one table instead of creating a new table for each subject. If you must store the same information in PHP, you may also prefer to do so using multi-dimensional arrays rather than separate arrays for each subject.
In this tutorial, we’ll learn how to sort a multi-dimensional array using a list of the tallest buildings in the world as an example. Our array will contain information about the name of the building, the city and country in which it is located, the number of floors and the total height in meters along with the year in which it was built.
When you want to sort values in a multi-dimensional array by a specific field, you can use the usort() function. The examples below will help you understand this technique better.
<?php
$tallest_buildings = [
["Building" => "Burj Khalifa","City" => "Dubai","Country" => "United Arab Emirates","Height" => 828,"Floors" => 163,"Year" => 2010],
["Building" => "Shanghai Tower","City" => "Shanghai","Country" => "China","Height" => 632,"Floors" => 128,"Year" => 2015],
["Building" => "Abraj Al-Bait Towers","City" => "Mecca","Country" => "Saudi Arabia","Height" => 601,"Floors" => 120,"Year" => 2012],
["Building" => "Ping An Finance Center","City" => "Shenzhen","Country" => "China","Height" => 599,"Floors" => 115,"Year" => 2017],
["Building" => "Lotte World Tower","City" => "Seoul","Country" => "South Korea" ,"Height" => 554,"Floors" => 123,"Year" => 2016]
];
function storey_sort($building_a, $building_b) {
return $building_a["Floors"] - $building_b["Floors"];
}
usort($tallest_buildings, "storey_sort");
foreach($tallest_buildings as $tall_building) {
list($building, $city, $country, $height, $floors) = array_values($tall_building);
echo $building." is in ".$city.", ".$country.". It is ".$height." meters tall with ".$floors." floors.\n";
}
/*
Ping An Finance Center is in Shenzhen, China. It is 599 meters tall with 115 floors.
Abraj Al-Bait Towers is in Mecca, Saudi Arabia. It is 601 meters tall with 120 floors.
Lotte World Tower is in Seoul, South Korea. It is 554 meters tall with 123 floors.
Shanghai Tower is in Shanghai, China. It is 632 meters tall with 128 floors.
Burj Khalifa is in Dubai, United Arab Emirates. It is 828 meters tall with 163 floors.
*/
?>
In the example above, the information about each building is stored in its own array within the main $tallest_buildings array. The storey_sort() function simply subtracts the number of floors in the second building from the first to determine which building is smaller according to our criteria. We don’t have to worry about returning a specific negative or positive value because all negative values mean less and all positive values mean greater.
In the end, we just iterate through the main array and print out information about each build.