0

How to sort an array using a custom sort function which requires additional data, in addition to the two objects being compared?

i.e. a structure something like this:

myfunction($item1, $item2, $data)
{
    $data->dataDependentSort($item1, $item2);
}

usort($array, "myfunction", $data);

Is this possible without global variables, or reimplementing usort()?

Usort will let you use a class function, but only a static function!

class MySorter
{
    function __construct($data)
    {
        $this->m_data = $data;
    }

    public function sortItems($item1, $item2)
    {
        ...
    }
}
$sorter = new MySorter($data);
usort($myarray, array("sorter", "sortItems")); // doesn't work because sorter isn't a class
usort($myarray, array("MySorter", "sortItems")); // doesn't work because sortItems can't access m_data
OJW
  • 4,232
  • 6
  • 35
  • 45
  • `usort($array, function() use($data) {} );` ? – splash58 Feb 12 '19 at 10:26
  • It's not really possible with a plain function, you'd need to use a class and pass `$data` to the constructor; or just use an *anonymous function* and `use`. – deceze Feb 12 '19 at 10:27
  • @Flash Please don't. – deceze Feb 12 '19 at 10:29
  • @deceze initialising a class would be great; however usort doesn't seem to accept a variable name, only a class name - i.e. it only works with static functions, which means it can't use the class data to assist with the sort operation. – OJW Feb 12 '19 at 11:55
  • The correct invocation there would be `array(new MySorter($data), 'sortItems')`. The first array items needs to be *an object*, not the name of a variable holding an object. – deceze Feb 12 '19 at 12:05
  • I think this is the answer - the documentation said to use a class name string as the first item in array, but using an object makes it work correctly. – OJW Feb 12 '19 at 12:10
  • @deceze marking this as a "duplicate" of a generalised discussion about variable scope makes it look like we're suggesting that the answer is to use nested functions or global variables. Would it be useful to add the array(new MySorter($data), 'sortItems') as an answer and remove the duplicate tags? – OJW Feb 12 '19 at 12:12
  • Why *don’t* you use an anonymous function…‽ – deceze Feb 12 '19 at 12:13
  • My sort function might be a hundred lines of code in this case, so would like to keep it readable and testable in its own class if possible. Perhaps you could add the anonymous function answer in case it helps other people? – OJW Feb 12 '19 at 12:22
  • Fair enough, found and added another more suitable duplicate. – deceze Feb 12 '19 at 12:43
  • One could also implement `__invoke`, then the array construct for a callable is not needed. – Yoshi Feb 12 '19 at 13:01

0 Answers0