How to Sort Arrays in PHP

It is always easier to grab a specific piece of information from sorted data, otherwise you have to go through each element of the array one at a time. For example, lets say you have stored the score of different students in a class in an array or a table. If the data is not sorted by the scores obtained, you will have to look at the score of each student in the class before you can tell who obtained the highest and lowest score. If the table was already sorted low to high on basis of scores, just looking at the score of first student would tell you the lowest mark.

Sorting makes a lot of tasks that require accessing or obtaining a specific set of data very easy and efficient. In this tutorial, we will learn how to use built-in PHP functions to sort different kinds of array.

Sorting an Array by Value

Sorting an array by the value of its elements is very easy in PHP. You can choose to maintain or discard key-value associations, and you can also define your own functions to dictate how elements are sorted. I’ll show you how in this section of the tutorial.

You can use the sort(&$array, $sort_flags) function to sort the values of an array from low to high. However, it will not maintain any key-value associations when sorting the array. New keys are assigned to sorted elements instead of a simple reordering. The optional second parameter allows you to specify how the elements should be sorted. It can have six different values:

  1. SORT_REGULAR—This will sort the values without changing their types.
  2. SORT_NUMERIC—This will sort the values by comparing them numerically.
  3. SORT_STRING—This will sort the values by comparing them as strings.
  4. SORT_LOCALE_STRING—This will compare the values as string based on the current locale. You can update the locale yourself by using setlocale().
  5. SORT_NATURAL—This will sort the items using “natural ordering” while comparing them as strings.
  6. SORT_FLAG_CASE—This can be combined with SORT_STRING or SORT_NATURAL to turn off case-sensitivity while sorting strings.

Here are a couple of sorting examples to help you quickly grasp the difference between all the 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 sorting, the numerical strings are converted to their numerical values and sorting is done accordingly. The string “Apple” is non-numeric so it is left untouched and compared as a string.

In the second example, numeric sorting, we want the data to be sorted based on numerical value so “Apple” is converted to the numeric value 0 and comes first. Rest of the values are sorted as expected.

In the third example, all the values are treated as strings. This means that instead of comparing the numerical value of 123 or 3249832 with 38, they are compared as strings—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 any key-value associations, so it isn’t a good pick for sorting associative arrays.

Sort an Associative Array

Key value associations become important when you are dealing with associative arrays. Consider the following example where an associative array is used to store the name of different persons and their favorite fruit. If you want to sort the list alphabetically by the name of the fruits, using the sort() function from previous section will result in 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, we not only lost the association of people with their favorite fruits, we also lost the names of the different people. Each sorted value has been assigned a new numeric index based on its position in the sorted array.

To help you tackle this problem easily, PHP has two different functions which maintain key-value association while sorting arrays by their values. 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 evident from the above example, the value Apple moves to the top while still maintaining its association with Patricia. The fruit names could be sorted in reverse just as easily by using the arsort() function.

Both these functions accept the same sorting flags as the value of their optional second parameter as sort() and rsort().

Sorting Array Elements by Value with User-Defined Functions

The four sorting functions can easily handle your common sorting needs with the help of different flags. However, sometimes your criteria for comparing the array elements might be different.

Lets say you have an array of random words which need to be sorted alphabetically. However, you also want to sort them based on their length before sorting them alphabetically. For example, zoo would come after apple in traditional alphabetical sorting. However, if want to show the short words before longer ones, zoo will appear before apple. In the same set of letters, ape would come before zoo due to alphabetical ordering.

Basically, the words are first sorted based on their length and then the words with same number of letters are sorted alphabetically within their own group. This type of sorting is not built into PHP so we will have to write our own sorting function.

What PHP does in this case is provide you a couple of functions which can be used to pass the array that you want to sort along with the name of your own sorting function.

You can use the usort() function to sort array values in regular arrays. Similarly, you can use the uasort() function to sort values in associative arrays while also maintaining key-value associations.

The code snippet below shows one way of accomplishing 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 the callback functions meant for custom sorting, we have to return an integer less than 0 to indicate that the first value is smaller than the second. Return 0 if the first value is equal to the second. Return an integer greater than 0 if the first value is greater than second.

Since our primary sorting criteria was string length, we directly return -1 if the first word is shorter than the second. Similarly, we directly return 1 if the first word is longer than the second. If the two words are equal in length, we compare them alphabetically using the strcmp() function and return its value.

As you can see in the output, our custom sort function reorders the words exactly the way we wanted.

Sorting an Array by Key

Sorting an array based on its keys is generally useful when you are dealing with associative arrays. For instance, you might have an array with information about the total number of airports in various countries. Assuming that the names of different countries are keys and the number of airports are values, you might want to sort the country names alphabetically. This is very easy to do with functions ksort() and krsort(). Both these functions will maintain the key-value association of array elements after sorting. The function ksort() sorts the keys from low to high and krsort() sorts the keys from high to low.

Here is a basic sorting example:

<?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 for sorting array keys using the uksort() function. Just like usort(), the callback function in uksort() also requires you to return an integer less than 0 if first key is considered less than the second one and an integer greater than 0 if first key is greater than 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 name of countries first by the length of their name and then alphabetically.

Sorting Multi-Dimensional Arrays in PHP

It is much more common in real life to deal with multi-dimensional information. For instance, institutions will store the marks of all students in a variety of subjects in a single table instead of creating new tables for each subject. If you have to store the same information in PHP, you would also prefer to do it using a multi-dimensional array instead of separate array for each subject.

In this tutorial, we will learn how to sort a multi-dimensional array using a list of tallest buildings in the world as example. Our array will contain information about the name of the building, the city and country where it is located, number of floors and total height in meters along with the year in which it was built.

When you want to sort the values in a multi-dimensional array based on the a particular field, you can simply use the usort() function. The example below should 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 above example, the information about each building is stored in its own array inside the main $tallest_buildings array. The storey_sort() function simply subtracts the numbers 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 smaller and all positive values mean bigger.

In the end, we just iterate through the main array and print out information about each building.

Final Thoughts

In this tutorial, I showed you some different functions in PHP which can be used to sort arrays either by their keys or their values. We also learned how to sort an array by its keys or values using our own custom sorting criteria with the help of uksrot() and uasort() functions. The final section discussed how to sort all the values in a multi-dimensional array using only a specific field.

I hope you learned something new from this tutorial. If you have any questions or suggestions please let me know in the comments. The best way to learn is to try and create some examples of your own, sorting arrays by using these functions.

Source:: Net Tuts

Leave a Reply

Your email address will not be published. Required fields are marked *