One option you have is to write your own sorting function, as I've already mentioned. In fact, I've done this numerous times. But why should I have to type out a quicksort algorithm -- slightly modified to compare objects or associative arrays -- rather than having the libraries do it and move on to more important things. This isn't CS class any more. I shouldn't have to "prove" that I understand the quicksort algorithm ... I need to get things done!
Well, as it turns out, PHP does indeed offer the capability to sort an array of objects. And it's not so bad. Check out usort. The basic concept is that you pass it the array of objects and a function (or static method) that'll act as a comparison function between two objects. This function is something you write yourself, since you're the one who knows about your classes. I usually put it right in the class itself, acting as a static method. Here's a quick example:
class Item {
var $a;
var $b;
function Item($pA, $pB) {
$this->a = $pA;
$this->b = $pB;
}
function _cmpAscA($m, $n) {
if ($m->a == $n->a) {
return 0;
}
return ($m->a < $n->a) ? -1 : 1;
}
function _cmpDescA($m, $n) {
if ($m->a == $n->a) {
return 0;
}
return ($m->a > $n->a) ? -1 : 1;
}
}
//let's make an array
$arr = array();
$arr[] = new Item(1, 2);
$arr[] = new Item(4, 3);
$arr[] = new Item(2, 3);
//now we can sort it!
$sorted = usort($arr, array('Item', '_cmpAscA'));
Note that the second parameter to the usort() function is an array. This is because I'm calling a static method. The first item('Item') denotes the class, and the second item('_cmpAscA') denotes the method name. If I had simply made a comparison function that wasn't in a class, the second parameter to usort() would have been a string, not an array.
I typically make two comparison functions per sortable field in my objects; I want to be able to sort ascending and descending, without having to muck with strrev(). My way is a bit faster ... but may force you to use a bit more code. It seems to me that that's a matter of personal preference. And I have this preference because I feel that it allows you to more accurately describe what you want. If you want to sort in descending order, you say "sort this in descending order," rather than "sort this and then reverse it."
Anyhow, usort() is a powerful tool to add to the toolbox. I know I'll be using it in the future for all my object-sorting needs. Hope you find it as useful.
10 comments:
That's great !
be careful, usort returns a boolean, not the sorted array.
Yes, you're right.
In my example, $sorted is a boolean that tells whether the sort was successful. $arr is the array, and it is sorted after the call to usort().
Thanks for helping to clarify that.
ah yes, I didn't get that...
hope it helps others
Hi
What if you would like to sort for both parameter 'a' and 'b' at the same time?
Primarily sort 'a' ascending, but if there are several identical 'a' then sort these for ascending 'b'.
I have an array of news-objects with several parameters. One of which is a 'date' (YYMMDD) and another is a 'time' (HH:MM). I would like to sort these objects for ascending 'date' and also for ascending 'time'.
Hi just want to ask if this will sort the alphanumeric files :) i just find my implementation weird as its not sorting my alphanumeric files.
Thanks
jefoy1101@gmail.com
Thank you.
It's just what I was looking for...
Thank you so much, regards from Spain.
mighty useful example, thanks from Sydney. Jeff.
Very useful comments.Thaiphoon, in order to do that kind of sorting, then code the sorting function like this:
function cmpDateTime($obj1, $obj2){
$date1 = $obj1->date;
$date2 = $obj2->date;
if($date1>$date2)return 1;
if($date2>$date2)return -1;
if($date==$date2){ //dates are the same, compare time
if($obj1->time > $obj2->time)return 1;
if($obj1->time < $obj2->time)return -1;
if($obj1->time == $obj2->time)return 0;
}
Muchos gracias "Anonymous".
I can see that logic.
Post a Comment