PHP - Sorting Arrays

There are a total of eleven functions in the PHP core whose only goal is to provide various methods of sorting the contents of an array. The simplest of these is sort(), which sorts an array based on its values:

<?php
$array = array('a' => 'foo', 'b' => 'bar', 'c' => 'baz');
sort($array);
var_dump($array);

?>
As you can see, sort() modifies the actual array it is provided, since the latter is passed by reference. This means that you cannot call this function by passing anything other than a single variable to it.
The result looks like this:
array(3) {
[0]=>
string(3) "bar"
[1]=>
string(3) "baz"
[2]=>
string(3) "foo"
}
Thus, sort() effectively destroys all the keys in the array and renumbers its elements starting from zero. If you wish to maintain key association, you can use asort() instead:
<?php
$array = array('a' => 'foo', 'b' => 'bar', 'c' => 'baz');
asort($array);
var_dump($array);
?>
This code will output something similar to the following:
array(3) {
["b"]=>
string(3) "bar"
["c"]=>
string(3) "baz"
["a"]=>
string(3) "foo"
}
Both sort() and asort() accept a second, optional parameter that allows you to specify how the sort operation takes place:
SORT_REGULAR Compare items as they appear in the array, without performing any kind of conversion.
This is the default behaviour.
SORT_NUMERIC Convert each element to a numeric value for sorting purposes.
SORT_STRING Compare all elements as strings.
The sorting operation performed by sort() and asort() simply takes into consideration either the numeric value of each element, or performs a byte-by-byte comparison of strings values. This can result in an “unnatural” sorting order—for example, the string value ’10t’ will be considered  “lower” than ’2t’ because it starts with the character 1, which has a lower value than 2. If this  sorting algorithm doesn’t work well for your needs, you can try using natsort() instead:
<?php
$array = array('10t', '2t', '3t');
natsort($array);
var_dump($array);
?>

This will output:
array(3) {
[1]=>
string(2) "2t"
[2]=>
string(2) "3t"
[0]=>
str
ing(3) "10t"
}
he natsort() function will, unlike sort(), maintain all the key-value associations in the array. A case-insensitive version of the function, natcasesort() also exists, but there is no reverse-sorting equivalent of rsort()
Other Sorting Options
In addition to the sorting functions we have seen this far, PHP allows you to sort by key (rather than by value) using the ksort() and krsort() functions, which work analogously to sort() and rsort():
<?php
$a = array ('a' => 30, 'b' => 10, 'c' => 22);
ksort($a);
var_dump($a);
?>


This will output:
array(3) {
["a"]=>
int(30)
["b"]=>
int(10)
["c"]=>
int(22)
}
Finally, you can also sort an array by providing a user-defined function:

<?php
function myCmp($left, $right){
// Sort according to the length of the value. // If the length is the same, sort normally

$diff = strlen($left) - strlen($right);
if(!$diff) {
return strcmp($left, $right);
}
return $diff;
}

$a = array('three','2two','one','two');
usort($a, 'myCmp');
var_dump ($a);
?>
This short script allows us to sort an array by a rather complicated set of rules: first, we sort according to the length of each element’s string representation. Elements whose values have the same length are further sorted using regular string comparison rules; our user-defined function must return a value of zero if the two values are to be considered equal, a value less than zero if the left-hand value is lower than the right-hand one, and a positive number otherwise. Thus, our script produces this output:
array(4) {
[0]=>
string(3) "one"
[1]=>
string(3) "two"
[2]=>
string(4) "2two"
[3]=>
string(5) "three"
}
As you can see, usort() has lost all key-value associations and renumbered our array; this can be avoided by using uasort() instead. You can even sort by key (instead of by value) by using uksort(). Note that there is no reverse-sorting version of any of these functions—because reverse sorting can performed by simply inverting the comparison rules of the user-defined function:
<?php
function myCmp($left, $right){
// Reverse-sort according to the length of the value.
// If the length is the same, sort normally
$diff = strlen($right) - strlen($left);
if(!$diff){
return strcmp($right, $left);
}
return $diff;
}
?>

This will result in the following output:
array(4) {
[0]=>
string(5) "three"
[1]=>
string(4) "2two"
[2]=>
string(3) "two"
[3]=>
str
ing(3) "one"
}
The Anti-Sort
There are circumstances where, instead of ordering an array, you will want to scramble its contents so that the keys are randomized; this can be done by using the shuffle() function:
<?php
$cards = array (1, 2, 3, 4);
shuffle($cards);
var_dump($cards);

?>
Since the shuffle() function randomizes the order of the elements of the array, the result of this script will be different every time—but here’s an example:
array(9) {
[0]=>
int(4)
[1]=>
int(1)
[2]=>
int(2)
[3]=>
int(3)
}
As you can see, the key-value association is lost; however, this problem is easily overcome by using another array function array_keys(), which returns an array whose values are the keys of the array passed to it.
For example:

<?php
$cards = array('a' => 10, 'b' => 12, 'c' => 13);
$keys = array_keys($cards);
shuffle($keys);

foreach($keys as $v) {
echo $v . " - " . $cards[$v] . "\n";
}
?>
As you can see, this simple script first extracts the keys from the $cards array, and then shuffles $keys, so that the data can be extracted from the original array in random order without losing key-value association. If you need to extract individual elements from the array at random, you can use array_rand(), which returns one or more random keys from an array:
<?php
$cards = array('a' => 10, 'b' => 12, 'c' => 13);
$keys = array_rand($cards, 2);
var_dump($keys);
var_dump($cards);
?>

If you run the script above, its output will look something like this:
array(2) {
[0]=>
string(1) "a"
[1]=>
string(1) "b"
}
array(3) {
["a"]=>
int(10)
["b"]=>
int(12)
["c"]=>
int(13)
}
As you can see, extracting the keys from the array does not remove the corresponding element from it—something you will have to do manually if you don’t want to extract the same keymore than once.

3 comments:

Related Posts Plugin for WordPress, Blogger...