Jump to content

[SOLVED] Merging object variable comparison functions for usort


Recommended Posts

Hi

 

I'm having a little problem with sorting. I've got an array of objects and I want to sort them by the given variable. It all works fine but I have a dozen different functions for each sort method. They work in a very similar fashion so I'd like to merge them.

 

So, I have an array with objects, can't really discuss specifics so I'll use an example. Let's say the array contains information on houses (i.e. house objects). These houses have certain variables, like Windows, Doors, Rooms, etc., which contain the number of the items (i.e. same data type: int). Because of having objects in the array, I need to use usort. Currently, this is how I'm calling the sort function:

usort($houses, $cmpfunc);

Where $cmpfunc is the user-specified sort method (windows, doors, rooms...).

 

And my comparison functions look like this:

function cmp_Windows($a, $b){
    return $a->Windows - $b->Windows;
}

function cmp_Doors($a, $b){
    return $a->Doors - $b->Doors;
}

function cmp_Rooms($a, $b){
    return $a->Rooms - $b->Rooms;
}

 

Now, since the functionality is essentially the same, it would be nice to be able to merge the functions, something like this:

function cmp_int($a, $b){
    return $a->$item - $b->$item;
}

 

But the problem is how to pass $item to the function. I got the impression that it is not possible to pass variables to a callback function. Does anyone know how to get around this?

Thanks for the answer, but I'm afraid the problem still exists. I would still need to have separate functions for comparing the number of windows, doors, rooms etc. Like so:

function cmp_Windows($a, $b) {
    return _cmp($a, $b, 'Windows');
}

function cmp_Doors($a, $b) {
    return _cmp($a, $b, 'Doors');
}

 

The problem is how to get the item type from where the usort is called to the comparison function. An ideal solution would be if it was possible to call usort like this:

usort($houses, cmp_int, 'Windows');

usort($houses, cmp_int, 'Doors');

 

Or give the item type as a callback function parameter:

usort($houses, cmp_int('Rooms') );

 

I wanted to get rid of the functions cmp_Windows, cmp_Doors and cmp_Rooms, and replace them with just one that would handle all item types.

Yes this is possible however you'd need a twist:

 

abstract class USorter {
     protected $_parameter = null;
     public function __construct($parameter) {
         $this->_parameter = $parameter;
     }
     public function sort(&$array) {
         return usort($array, array(&$this, '_sort'));
     }
     abstract protected function _sort($a, $b);
}

//your usort
class MySort extends USorter {
     protected function _sort($a, $b) {
          return $a->{$this->_parameter} - $b->{$this->_parameter};
     }
}

 

Call like:

$sort = new MySort('Windows');
$sort->sort($array);

 

However I'm not sure if you can pass protected methods altough you pass $this. However if not, then change the function name and change protected to public. If you want to expand it further I suggest you take a look at the Strategy pattern.

 

Add a setParameter($param) method. That will allow you to do something like:

$sort = new MySort('Windows'); //initialize for sorting on Windows
$sort->sort($array);
$sort->setParameter('Doors');
$sort->sort($array);
//..

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.