Quite often I find myself having an array of objects and needing to sort that array by one or more of the properties in the objects… Imagine, for example, getting a large result set from Zend_Db, or something similar, and ordering in the query just takes too long. Or perhaps you’re getting results from a web service and that service doesn’t return the results in the order you’d like to use. Have you ever found yourself in that situation, too? On looking at the usort documentation one day I came across a comment by someone called Will Shaver that did almost what I wanted. With a little adaptation for my own use (being able to change the sort order, for example), it has become one of my favourite functions to use for sorting.
/**
* Sort an array of objects.
*
* You can pass in one or more properties on which to sort. If a
* string is supplied as the sole property, or if you specify a
* property without a sort order then the sorting will be ascending.
*
* If the key of an array is an array, then it will sorted down to that
* level of node.
*
* Example usages:
*
* osort($items, 'size');
* osort($items, array('size', array('time' => SORT_DESC, 'user' => SORT_ASC));
* osort($items, array('size', array('user', 'forname'))
*
* @param array $array
* @param string|array $properties
*/
public static function osort(&$array, $properties)
{
if (is_string($properties)) {
$properties = array($properties => SORT_ASC);
}
uasort($array, function($a, $b) use ($properties) {
foreach($properties as $k => $v) {
if (is_int($k)) {
$k = $v;
$v = SORT_ASC;
}
$collapse = function($node, $props) {
if (is_array($props)) {
foreach ($props as $prop) {
$node = (!isset($node->$prop)) ? null : $node->$prop;
}
return $node;
} else {
return (!isset($node->$props)) ? null : $node->$props;
}
};
$aProp = $collapse($a, $k);
$bProp = $collapse($b, $k);
if ($aProp != $bProp) {
return ($v == SORT_ASC)
? strnatcasecmp($aProp, $bProp)
: strnatcasecmp($bProp, $aProp);
}
}
return 0;
});
}
Now a few cools things about the function:
- It uses anonymous/lambda functions (or closures, whatever your prefer to call them), and that’s just plain fun
- You can sort on more than one property and because the sorting is recursive, it’ll sort the second property within the confines of the first, the third within the confines of the second, and so on. Think sorting in SQL
- You can sort in ascending or descending order for any of the properties
- It retains key associations so you could use this on an associative array of objects
- If the parameter you want to sort on is an array itself then you can use any value (by specifying it’s key) in that array as the sorting value
Did you like this? Share it:
Recent Comments