Heimo Posted July 16, 2009 Share Posted July 16, 2009 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? Quote Link to comment https://forums.phpfreaks.com/topic/166201-solved-merging-object-variable-comparison-functions-for-usort/ Share on other sites More sharing options...
ignace Posted July 16, 2009 Share Posted July 16, 2009 function cmp_Windows($a, $b) { return _cmp($a, $b, 'Windows'); } .. function _cmp($a, $b, $itemName) { return $a->{$itemName} - $b->{$itemName}; } Quote Link to comment https://forums.phpfreaks.com/topic/166201-solved-merging-object-variable-comparison-functions-for-usort/#findComment-876426 Share on other sites More sharing options...
Heimo Posted July 16, 2009 Author Share Posted July 16, 2009 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. Quote Link to comment https://forums.phpfreaks.com/topic/166201-solved-merging-object-variable-comparison-functions-for-usort/#findComment-876456 Share on other sites More sharing options...
Heimo Posted July 17, 2009 Author Share Posted July 17, 2009 Bump? Is this even possible? Maybe something with create_function (although it doesn't seem like a very secure function)? Any alternative methods are welcome. Quote Link to comment https://forums.phpfreaks.com/topic/166201-solved-merging-object-variable-comparison-functions-for-usort/#findComment-876966 Share on other sites More sharing options...
ignace Posted July 19, 2009 Share Posted July 19, 2009 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); //.. Quote Link to comment https://forums.phpfreaks.com/topic/166201-solved-merging-object-variable-comparison-functions-for-usort/#findComment-878111 Share on other sites More sharing options...
Heimo Posted July 20, 2009 Author Share Posted July 20, 2009 Thank you. A little tricky but clever. Seems to be working as intended, marking as solved. Quote Link to comment https://forums.phpfreaks.com/topic/166201-solved-merging-object-variable-comparison-functions-for-usort/#findComment-878456 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.