Reputation: 282865
What I want to do is create a Comparable
class, similar to IComparable
in .NET, such that you can instantiate it like so:
$cmp = new MultiArrayCompare(2);
And then you can sort an array via:
usort($myArray, $cmp);
And it will sort an array of arrays on the 2nd index. To do that, I imagine usort
would try to call $cmp
like a function, so I'd have to override that behaviour somehow. It doesn't look like __call
does what I want (thought for a minute it was like Python's __call__
).
If this isn't possible... is there another nice way to create a general solution to this problem? Where you can create a user-defined sorting function but give pass it some value ("2" in this case)?
Using __invoke
I was able to create these classes:
abstract class Comparable {
abstract function Compare($a, $b);
function __invoke($a, $b) {
return $this->Compare($a, $b);
}
}
class ArrayCompare extends Comparable {
private $key;
function __construct($key) {
$this->key = $key;
}
function Compare($a, $b) {
if($a[$this->key] == $b[$this->key]) return 0;
return $a[$this->key] < $b[$this->key] ? -1 : 1;
}
}
class ArrayCaseCompare extends Comparable {
private $key;
function __construct($key) {
$this->key = $key;
}
function Compare($a, $b) {
return strcasecmp($a[$this->key], $b[$this->key]);
}
}
Which I can use to sort an array of arrays:
$arr = array(
array(1,2,3),
array(2,3,4),
array(3,2,4),
)
usort($arr,new ArrayCompare(1));
Upvotes: 2
Views: 179
Reputation: 316969
You are looking for __invoke
:
The __invoke() method is called when a script tries to call an object as a function.
class SortAscending
{
public function __invoke($a, $b)
{
return $a - $b;
}
}
$numbers = array(4,7,2,3,9,1);
usort($numbers, new SortAscending);
print_r( $numbers );
Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 7 [5] => 9 )
The slimmer alternative is using a Closure. Your code would simply be:
$arr = array(
array(1,2,3),
array(2,3,4),
array(3,2,4),
);
$key = 1;
usort($arr, function($a, $b) use ($key) {
return $a[$key] - $b[$key];
});
or - reusable and configurable (demo):
$ArrayCompare = function ($index) {
return function($a, $b) use ($index) {
return $a[$index] - $b[$index];
};
};
usort($arr, $ArrayCompare(1));
Apart from that, you can use basically any method you want and specify the method in the callback:
usort($arr, array(new ArrayCompare(1), 'Compare'));
The above would achieve the same without magic. See the chapter on callbacks for additional options.
Upvotes: 5
Reputation: 5377
Why you don't create a Comparer
class that provides a set of static compareXXX()
methods?
To me this looks much cleaner with an object oriented approach in mind...
Upvotes: 1
Reputation: 71918
Maybe you are looking for __invoke()?
Example from the manual:
class CallableClass
{
public function __invoke($x)
{
var_dump($x);
}
}
$obj = new CallableClass;
$obj(5);
var_dump(is_callable($obj));
Upvotes: 3