2012-11-27 40 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的回答。