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:
$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:
$array = array(’a’
=> ’foo’, ’b’ => ’bar’, ’c’ => ’baz’);
asort($array);
var_dump($array);
This code will ou tput 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:
$array = array(’10t’,
’2t’, ’3t’);
natsort($array);
var_dump($array);
This will output:
Arrays ” 63
array(3) {
[1]=>
string(2)
"2t"
[2]=>
string(2)
"3t"
[0]=>
string(3)
"10t"
}
The 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():
$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:
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:
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]=>
string(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:
$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:
$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:
$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 key more than
once.
0 Comment to " PHP Sorting Array "
Post a Comment