我想要做的是创建一个类似于.NET中的IComparable
的Comparable
类,这样您就可以像这样实例化它:
$cmp = new MultiArrayCompare(2);
然后你可以通过对数组进行排序
usort($myArray, $cmp);
它将对第二个索引上的数组进行排序。要做到这一点,我想usort
会尝试像函数一样调用$cmp
,所以我必须以某种方式覆盖这种行为。看起来__call
并不像我想做的那样(我想了一会儿,它就像Python的__call__
)。
如果这不可能。。。有没有另一种很好的方法来创建这个问题的通用解决方案?在哪里可以创建一个用户定义的排序函数,但给它一些值(在这种情况下为"2")?
使用__invoke
,我能够创建以下类:
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]);
}
}
我可以用它对数组进行排序:
$arr = array(
array(1,2,3),
array(2,3,4),
array(3,2,4),
)
usort($arr,new ArrayCompare(1));
您正在寻找__invoke
:
当脚本试图将对象作为函数调用时,会调用__invoke()方法。
示例:
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 )
更苗条的选择是使用闭合。你的代码很简单:
$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];
});
或可重复使用和可配置(演示):
$ArrayCompare = function ($index) {
return function($a, $b) use ($index) {
return $a[$index] - $b[$index];
};
};
usort($arr, $ArrayCompare(1));
除此之外,您基本上可以使用任何您想要的方法,并在回调中指定方法:
usort($arr, array(new ArrayCompare(1), 'Compare'));
如果没有魔法,以上内容也会实现。有关其他选项,请参阅有关回调的章节。
也许您正在寻找__invoke()?
手册示例:
class CallableClass
{
public function __invoke($x)
{
var_dump($x);
}
}
$obj = new CallableClass;
$obj(5);
var_dump(is_callable($obj));
为什么不创建一个提供一组静态compareXXX()
方法的Comparer
类?
对我来说,考虑到面向对象的方法,这看起来更干净。。。