我找到了一些我一直在使用的排序问题的解决方案,但代码在PHP中使用了匿名函数。我使用的是5.2.17版本,我认为不支持匿名功能。
我如何更改以下代码块,以便在PHP 5.2.17中使用它们
$keys = array_flip($order);
usort($items, function($a, $b) use($keys)
{
return $keys[$a['id']] - $keys[$b['id']];
});
来自PHP sort multidimensional array by other array
和
$sorted = array_map(function($v) use ($data) {
return $data[$v - 1];
}, $order);
来自PHP - Sort multi-dimensional array by another array
更新: 其中一个问题是我不确定如何使用变量$ a,$ b和$ v。所以我不确定如何创建正常的函数,从而绕过了anon函数。
答案 0 :(得分:3)
两个匿名函数都使用use
子句将变量传递到本地范围。
您可以使用对象方法实现相同的目标,其中对象将这些变量作为属性。
在对象方法中,您可以访问这些。
$sorted = array_map(function($v) use ($data) {
return $data[$v - 1];
}, $order);
示例性映射对象则可能如下所示:
class MapObj
{
private $data;
public function __construct($data) {
$this->data = $data;
}
public function callback($v) {
return $this->data[$v - 1];
}
}
正如您所看到的,它具有相同的功能,但只是用PHP 5.2语法编写。
它的用法:
$map = new MapObj($data);
$callback = array($map, 'callback');
$sorted = array_map($callback, $order);
这就是它的工作原理。对象方法的回调总是以array
的形式写成,有两个成员,第一个是对象实例,第二个是对象方法的名称。
当然你可以将映射函数扩展到映射对象中,所以它更直接:
class MapObj
{
...
public function map(array $order) {
$callback = array($this, 'callback');
return array_map($callback, $order);
}
}
新用法:
$map = new MapObj($data);
$sorted = $map->map($order);
正如您所看到的,这可能会使用法更直接。我必须承认,我的方法命名在这里并不是很精彩,所以我给你的改进留下了一些空间。
另一个好处是,您可以将回调方法的可见性设为私有。
将数据作为映射函数的参数传递给回调的情况。那是因为你写道你已经有了一个你想要使用的类,但是你无法触及构造函数。所以给出的例子有点短。
这是另一个不使用构造函数的示例,我删除了它:
class MyObj
{
private $data;
private function callback($v) {
return $this->data[$v - 1];
}
public function map($order, $data) {
$callback = array($this, 'callback');
$this->data = $data;
return array_map($callback, $order);
}
}
正如您所看到的,不再需要构造函数来传递$data
,而是将其作为附加参数传递给map()
方法。用法:
$myObj = new MyObj(....); // somewhere.
// later on:
$myObj->map($order, $data);
// could be also:
$this->map($order, $data);
如您所见,您如何设置私有成员变量取决于您。做适合自己的工作。
答案 1 :(得分:0)
这里有一个闭包而不是$data
- 如果没有匿名函数,就不可能100%重写它。这是最接近的近似值:
function _array_sort_callback($a, $b) {
global $_array_sort_callback__keys;
return $_array_sort_callback__keys[$a['id']] - $_array_sort_callback__keys[$b['id']];
}
... {
$keys = array_flip($order);
global $_array_sort_callback__keys;
$_array_sort_callback__keys = $keys;
usort($items, "_array_sort_callback");
}
请注意,我已经为全局名称添加了前缀,以避免发生冲突。功能名称和全局名称在您的应用程序中都必须是唯一的。
另外,请记住PHP 5.2.17已过时且不受支持。你应该尽快迁移它。
答案 2 :(得分:0)
如果你想模仿一个闭包,你在特定时间快照变量,你可以使用一个简单的基类作为值的容器,然后只需定义子类来实现比较逻辑。
未测试
// base class exists purely to capture the value of some variables at instantiation time
// kinda like a closure
class VarCapture {
protected $vars;
function __construct($vars) {
$this->vars = $vars;
}
}
class ItemComparer extends VarCapture {
function compare($a, $b) {
$keys = $this->vars['keys'];
return $keys[$a['id']] - $keys[$b['id']];
}
}
class PluckMapper extends VarCapture {
function pluck($v) {
$data = $this->vars['data'];
return $data[$v - 1];
}
}
$keys = array_flip($order);
$ic = new ItemComparer(compact('keys'));
$callable = array($ic, 'compare');
usort($items, $callable);
$pm = new PluckMapper(compact('data'));
$callable = array($mp, 'pluck');
$sorted = array_map($callable, $order);
请注意,我使用了php的回调伪类型 http://php.net/manual/en/language.types.callable.php
答案 3 :(得分:0)
您也可以将其重新编写为5.3之前的匿名函数,即create_function()
。虽然create_function()
函数通常不作为闭包,但您可以使用一些技巧(不使用全局变量)使它们在某些有限的情况下用作闭包。您将关闭的变量直接编码到函数的源中。限制是数据只是单向进入;封闭变量只能是“简单”数据类型,如数字,字符串和数组;使用create_function
创建的函数永远不会被释放,泄漏内存;再加上效率不高。但我认为这对你的例子来说已经足够了(假设你只使用数组和字符串等)。
$keys = array_flip($order);
usort($items, create_function('$a,$b', '$keys = '.var_export($keys,true).';
return $keys[$a["id"]] - $keys[$b["id"]];
'));
和
$sorted = array_map(create_function('$v', '$data = '.var_export($data,true).';
return $data[$v - 1];
'), $order);
更一般的5.3之前的解决方案是使用对象和方法作为闭包,就像hakra的回答一样。