2012-11-27 36 views
2

我已经找到了一些排序问题的解决方案,我一直在使用,但代码在PHP中使用匿名函数。我使用版本5.2.17,我相信匿名函数不受支持。PHP修改代码以避免匿名函数

我怎么会更改下面的代码块,所以我可以在PHP 5.2.17

​​

使用它们从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。所以我不确定如何创建正常的函数,从而绕过了匿名函数。

+0

anon funcs是在5.3中添加的,所以是的,你是对的......不支持:http://php.net/manual/en/functions.anonymous.php。通过使用通常定义的常规功能来解决这个问题。 'usort($ items,“your_func_here”)'。 –

+0

谢谢 - 问题是我真的不知道匿名函数是如何工作的。例如,我无法弄清变量$ a,$ b和$ v是如何使用的。他们来自哪里? –

+0

将函数声明为常规函数,并将其作为字符串传递。 – meagar

回答

2

这两个匿名函数都使用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); 

正如你所看到的,你如何设置私有成员变量取决于你。做适合的工作。

+0

哇,非常详细 - 谢谢。我是否必须在自己的类中声明函数?或者可以将这一切都包装到我从中调用它的课程中。 –

+0

当然,如果你已经有了类定义,你可以添加回调函数。你应该让它们变成私有的,然后调用你的类中的映射和排序功能,然后它甚至是非常有光泽的! – hakre

+0

啊对不起,我在这里很慢。这是抛出我的公共函数__construct($ data)。我无法将这些添加到当前课程中。对不起,如果这是显而易见的...过了漫长的一天... –

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已过时并且不受支持。你应该尽快迁离。

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

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的回答。