PHP Sort Array By SubArray Value
What is the best way to order the array in an incremental way, based on the optionNumber ? So the results look like:
Array ( [0] => Array ( [configuration_id] => 8 [id] => 1 [optionNumber] => 1 [optionActive] => 1 [lastUpdated] => 2010-03-17 15:44:12 ) [1] => Array ( [configuration_id] => 9 [id] => 1 [optionNumber] => 2 [optionActive] => 1 [lastUpdated] => 2010-03-17 15:44:12 ) [2] => Array ( [configuration_id] => 10 [id] => 1 [optionNumber] => 3 [optionActive] => 1 [lastUpdated] => 2010-03-17 15:44:12 ) )
8 Answers 8
function cmp_by_optionNumber($a, $b) < return $a["optionNumber"] - $b["optionNumber"]; >. usort($array, "cmp_by_optionNumber");
In PHP ≥5.3, you should use an anonymous function instead:
Note that both code above assume $a[‘optionNumber’] is an integer. Use @St. John Johnson’s solution if they are strings.
usort($array, function ($a, $b) < return $a['optionNumber'] $b['optionNumber']; >);
That doesn’t really helpe me as usort requires I provide it a function to use — which is the difficult bit I can’t get my head round
Well he just gave you the function to use. And you’re going to have to accept that there’s not always a built-in function to do what you want, you have to write it yourself. Comparison functions just require a return of 1, 0, or -1 indicating the sort order for two elements.
I looked further into usort and it is actually quite cool. I wrote a simple comparison function to the one above, however missed out the ‘==’. Thanks for the help guys
usort($array, 'sortByOption'); function sortByOption($a, $b)
@BenSinclair, that’s because Kenny’s solution is for numbers, this solution is for strings. They are both correct 🙂 +1 for this alternative.
can we define key for second order in array means we do first sorting with optionNumber then sorting with lastUpdated. How can do this thing?
I used both solutions by KennyTM and AJ Quick and came up with a function that can help in this issue for many cases like using ASC or DESC sorting or preserving keys or if you have objects as children of array.
Here is this function (works for PHP7 and higher because of spaceship operator):
/** * @param array $array * @param string $value * @param bool $asc - ASC (true) or DESC (false) sorting * @param bool $preserveKeys * @return array * */ function sortBySubValue($array, $value, $asc = true, $preserveKeys = false) < if ($preserveKeys) < $c = []; if (is_object(reset($array))) < foreach ($array as $k =>$v) < $b[$k] = strtolower($v->$value); > > else < foreach ($array as $k =>$v) < $b[$k] = strtolower($v[$value]); >> $asc ? asort($b) : arsort($b); foreach ($b as $k => $v) < $c[$k] = $array[$k]; >$array = $c; > else < if (is_object(reset($array))) < usort($array, function ($a, $b) use ($value, $asc) < return $a-> == $b-> ? 0 : ($a-> $b->) * ($asc ? 1 : -1); >); > else < usort($array, function ($a, $b) use ($value, $asc) < return $a[$value] == $b[$value] ? 0 : ($a[$value] $b[$value]) * ($asc ? 1 : -1); >); > > return $array; >
sortBySubValue($array, 'optionNumber', true, false);
The first part can be rewritten using uasort() and the function will be shorter (works for PHP7 and higher because of spaceship operator):
/** * @param array $array * @param string $value * @param bool $asc - ASC (true) or DESC (false) sorting * @param bool $preserveKeys * @return array * */ function sortBySubValue($array, $value, $asc = true, $preserveKeys = false) < if (is_object(reset($array))) < $preserveKeys ? uasort($array, function ($a, $b) use ($value, $asc) < return $a-> == $b-> ? 0 : ($a-> $b->) * ($asc ? 1 : -1); >) : usort($array, function ($a, $b) use ($value, $asc) < return $a-> == $b-> ? 0 : ($a-> $b->) * ($asc ? 1 : -1); >); > else < $preserveKeys ? uasort($array, function ($a, $b) use ($value, $asc) < return $a[$value] == $b[$value] ? 0 : ($a[$value] $b[$value]) * ($asc ? 1 : -1); >) : usort($array, function ($a, $b) use ($value, $asc) < return $a[$value] == $b[$value] ? 0 : ($a[$value] $b[$value]) * ($asc ? 1 : -1); >); > return $array; >
Sorting Arrays
PHP has several functions that deal with sorting arrays, and this document exists to help sort it all out.
- Some sort based on the array keys, whereas others by the values: $array[‘key’] = ‘value’;
- Whether or not the correlation between the keys and values are maintained after the sort, which may mean the keys are reset numerically (0,1,2 . )
- The order of the sort: alphabetical, ascending (low to high), descending (high to low), natural, random, or user defined
- Note: All of these sort functions act directly on the array variable itself, as opposed to returning a new sorted array
- If any of these sort functions evaluates two members as equal then they retain their original order. Prior to PHP 8.0.0, their order were undefined (the sorting was not stable).
Function name | Sorts by | Maintains key association | Order of sort | Related functions |
---|---|---|---|---|
array_multisort() | value | string keys yes, int keys no | first array or sort options | array_walk() |
asort() | value | yes | ascending | arsort() |
arsort() | value | yes | descending | asort() |
krsort() | key | yes | descending | ksort() |
ksort() | key | yes | ascending | krsort() |
natcasesort() | value | yes | natural, case insensitive | natsort() |
natsort() | value | yes | natural | natcasesort() |
rsort() | value | no | descending | sort() |
shuffle() | value | no | random | array_rand() |
sort() | value | no | ascending | rsort() |
uasort() | value | yes | user defined | uksort() |
uksort() | key | yes | user defined | uasort() |
usort() | value | no | user defined | uasort() |
User Contributed Notes 2 notes
While this may seem obvious, user-defined array sorting functions ( uksort(), uasort(), usort() ) will *not* be called if the array does not have *at least two values in it*.
function usortTest ( $a , $b ) var_dump ( $a );
var_dump ( $b );
return — 1 ;
>
$test = array( ‘val1’ );
usort ( $test , «usortTest» );
$test2 = array( ‘val2’ , ‘val3’ );
usort ( $test2 , «usortTest» );
The first array doesn’t get sent to the function.
Please, under no circumstance, place any logic that modifies values, or applies non-sorting business logic in these functions as they will not always be executed.
Another way to do a case case-insensitive sort by key would simply be:
uksort ( $array , ‘strcasecmp’ );
?>
Since strcasecmp is already predefined in php it saves you the trouble to actually write the comparison function yourself.
Mastering PHP arrays: Array sorting
Sorting is an operation that arranges data in a specified way. PHP has several functions that deal with sorting arrays. Let’s examine these functions.
Good overview of sorting functions can be found in PHP manual: Sorting Arrays. All sorting functions act directly on an array variable itself because the variable is passed to sort function by reference, as opposed to returning a new sorted array. Because only variables can be passed by reference, you will get Fatal error when you try to pass array directly as a function argument.
Sort functions return true on success or false and warning message when parameter type differs from array.
1php 2 3$array = [14, 1, 22, 8, 7]; 4$return = sort($array); 5var_dump($return); // bool(true) 6 7$string = 'bar'; 8$return = sort($string); 9Warning: sort() expects parameter 1 to be array, string given in php shell code on line 1 10var_dump($return); // bool(false)
If two array members are evaluated as equal then the order is undefined. It’s unknown which number 1 will be at $array[0] or $array[1] :
1php 2 3$array = [3, 1, 2, 1]; 4sort($array);
Most PHP sorting functions uses implementation of Quicksort.
Sorting single arrays
The simplest of sorting functions is sort, which sorts an array by its values from lowest to highest and doesn’t maintain the key association.
Modified sort functions offer also sorting by key (ksort), key-value association (asort), reverse sorting (rsort), user-defined comparison function (usort) and different variations of these functions. (arsort, krsort, uksort, ursort). There’s no reverse sorting version of user-defined sorting functions because reverse sorting can be performed by updating comparison rules.
Be careful when sorting arrays with mixed types of values because the sort function can produce unpredictable results. This also applies to sort functions with sort flag different to SORT_REGULAR, which is default sort flag for most sorting functions.
Example array with various types of scalar values:
1php 2 3$array = [ 4 true, 5 false, 6 'Hello', 7 'hi', 8 50, 9 0.25, 10 '4', 11 'hello', 12 '045', 13 '03', 14 'ABC', 15 "\x41", // hexadecimal ASCII code for letter 'A' 16 0x17, // hexadecimal representation of number 23 17 020, // octal representation of number 16 18 ];
Output of the sort($array) function for various sort flags will be:
As you can see sorted array differs for each sort flag. Comparison of sorted keys and values is case sensitive by default. For case-insensitive comparison, SORT_FLAG_CASE combination with SORT_STRING or SORT_NATURAL can be used.
1php 2 3$oranges = ['Orange1', 'orange3', 'orange1','Orange4']; 4 5sort($oranges, SORT_STRING); 6var_dump($oranges); 7 8sort($oranges, SORT_STRING | SORT_FLAG_CASE); 9var_dump($oranges);
For natural ordering the natsort function and for the case-insensitive version the natcasesort function can be used. These functions are shortcuts for sort function with SORT_FLAG_CASE for case-sensitive version and SORT_FLAG_CASE | SORT_FLAG_CASE for case insensitive version. Natural ordering is using Natural Order String Comparison which is more human-friendly then a byte-by-byte comparison of sort function.
Other sorting options
Sort functions, with user-defined comparison function, give you an option to create a custom comparison function. User-defined comparison function sort family accept callback functions as a parameter. Callback functions can be simple functions, but also object methods, including static class methods and anonymous functions.
Sort function expects integer as a return value and all returning non-integer values are cast to an integer.
This behaviour is called type juggling and you can read more about it in PHP Manual: Type Juggling
Expected compare function return values:
- $first_compared_value == $second_compared_value => integer equal to zero; 0
- $first_compared_value < $second_compared_value =>integer less then zero; e.g -1
- $first_compared_value > $second_compared_value => integer greater than zero; e.g 1
Example: Interpolation of sort function with SORT_STRING sort flag using anonymous function/closure.
1php 2 3$array = ['Hello', 'Ahoy','Hi', 'hello']; 4 5usort($array, function($a, $b) 6 return strcmp($a, $b); 7>); 8 9var_dump($array);
The output of this script will be:
It is possible to create a comparison function like this, because strcmp() function returns values as an usort() expectation defined earlier ( < 0 if str1 is less than str2; >0 if str1 is greater than str2, and 0 if they are equal).
Example: Sort by occurrence of character ‘o’:
1php 2 3$array = ['Hello World', 'Ahoy','Hi']; 4 5function occurrenceOfO($a, $b) 6 7 $a_o_count = substr_count($a, 'o'); 8 $b_o_count = substr_count($b, 'o'); 9 10 if ($a_o_count === $b_o_count) 11 return 0; 12 > 13 14 return $a_o_count >= $b_o_count; 15> 16 17usort($array, 'occurrenceOfO'); 18var_dump($array);
This outputs the following:
As you can see the usort function gives you an option to create complex sorting functions. Note that this function doesn’t maintain key-value association and assigns new keys to elements. If you want to maintain association use uasort function instead.
PHP 7 introduced three-way comparison operator ( ), also known as the “spaceship operator”, which has similar behaviour to the strcmp() function. This makes easier to write callbacks for comparison functions and return correct values expected by this function.
Example of spaceship operator behaviour:
1php 2 3echo 1 1; // 0 4 echo 1 2; // -1 5 echo 2 1; // 1
Sorting multi-arrays
For sorting multiple or multi-dimensional arrays the array_multisort function can be used. This function works more like database style sorting — ‘ORDER BY’ multiple columns statement in SQL query, rather than a sort function which excepts multiple arrays and sorts these arrays independently.
1php 2 3$magazine[] = ['year' => 2015, 'month' => 1, 'issue' => 1]; 4$magazine[] = ['year' => 2014, 'month' => 12, 'issue' => 4]; 5$magazine[] = ['year' => 2015, 'month' => 2, 'issue' => 2]; 6$magazine[] = ['year' => 2015, 'month' => 3, 'issue' => 3]; 7$magazine[] = ['year' => 2015, 'month' => 1, 'issue' => 2]; 8 9var_dump($magazine); 10array_multisort($magazine); 11var_dump($magazine);
The output of this script will be:
As you can see from outputted data, the array was sorted by year at first place, then by month and an issue number at last place.
Array shuffling
For randomizing the order of elements in an array the shuffle function can be used. This function doesn’t preserve key-value association and PHP doesn’t provide a built-in function for this.
The output of this script will differ on each call:
1php 2 3$numbers = [1, 2, 3, 4, 5]; 4shuffle($numbers); 5var_dump($numbers);