2011-03-30 115 views
77

我有以下代碼:PHP array_filter帶參數

function lower_than_10($i) { 
    return ($i < 10); 
} 

,我可以用它來過濾像這樣的數組:

$arr = array(7, 8, 9, 10, 11, 12, 13); 
$new_arr = array_filter($arr, 'lower_than_10'); 

我如何添加參數lower_than_10以便它也可以接受要檢查的數字?喜歡,如果我有這個:

function lower_than($i, $num) { 
    return ($i < $num); 
} 

如何從array_filter調用它傳遞10到$ num或任何數字?

回答

54

作爲替代@查爾斯的solution using closures,實際上你可以找到的文檔頁面上的例子in the comments的想法是,創建一個對象具有期望的狀態($num)和回調方法(以$i作爲參數):

class LowerThanFilter { 
     private $num; 

     function __construct($num) { 
       $this->num = $num; 
     } 

     function isLower($i) { 
       return $i < $this->num; 
     } 
} 

用法(demo):

$arr = array(7, 8, 9, 10, 11, 12, 13); 
$matches = array_filter($arr, array(new LowerThanFilter(12), 'isLower')); 
print_r($matches); 

作爲旁註,您現在可以用更通用的NumericComparisonFilter替換LowerThanFilter,方法如isLower,isGreater,isEqual等只是一個想法—和demo ...

+0

良好的解決方法。爲了維護代碼,它可能有助於修改類以支持更可讀的方法調用: $ matches = $ myobj-> ArraySelect(Array('from'=> $ arr,'where'=> $ foo,'lessthan'=> 12)) – dreftymac 2011-11-10 00:31:32

+0

我不是一個php savy,所以也許這是一個明顯的問題,但是如何將一個數組傳遞給array_filter並使其工作?除了有人的評論外,文檔從來沒有談論過這個問題。 – 2017-08-17 17:40:11

+1

@NicolaPedretti我假設你在談論'array_filter'的秒參數?它只是一個「可調用的」;在上述匹配「類型3:對象方法調用」的情況下:'數組()',參見。 [PHP:Callbacks/Callables - Manual](http://php.net/manual/en/language.types.callable.php)。 – jensgram 2017-08-18 04:51:14

32

在PHP 5.3或更好的,你可以使用一個closure

function create_lower_than($number = 10) { 
// The "use" here binds $number to the function at declare time. 
// This means that whenever $number appears inside the anonymous 
// function, it will have the value it had when the anonymous 
// function was declared. 
    return function($test) use($number) { return $test < $number; }; 
} 

// We created this with a ten by default. Let's test. 
$lt_10 = create_lower_than(); 
var_dump($lt_10(9)); // True 
var_dump($lt_10(10)); // False 
var_dump($lt_10(11)); // False 

// Let's try a specific value. 
$lt_15 = create_lower_than(15); 
var_dump($lt_15(13)); // True 
var_dump($lt_15(14)); // True 
var_dump($lt_15(15)); // False 
var_dump($lt_15(16)); // False 

// The creation of the less-than-15 hasn't disrupted our less-than-10: 
var_dump($lt_10(9)); // Still true 
var_dump($lt_10(10)); // Still false 
var_dump($lt_10(11)); // Still false 

// We can simply pass the anonymous function anywhere that a 
// 'callback' PHP type is expected, such as in array_filter: 
$arr = array(7, 8, 9, 10, 11, 12, 13); 
$new_arr = array_filter($arr, $lt_10); 
print_r($new_arr); 
+1

感謝您的解決方案,它是整齊的,但我有PHP 5.2在服務器上,所以我必須使用jensgram's :) – pistacchio 2011-03-30 08:27:39

+0

在php <5.3中,您可以使用'create_function()'。 – 2011-03-30 17:40:31

+3

'create_function()'基本上是'eval()'與另一個名字,並且同樣邪惡。使用它應該是不鼓勵的。在接受的答案中給出的古怪的基於類的解決方法比在這種情況下使用'create_function()'更好的解決方案。 – Charles 2011-03-30 17:43:26

12

在擴展jensgram答案您可以通過使用__invoke()魔術方法添加一些更神奇。

class LowerThanFilter { 
    private $num; 

    public function __construct($num) { 
     $this->num = $num; 
    } 

    public function isLower($i) { 
     return $i < $this->num; 
    } 

    function __invoke($i) { 
     return $this->isLower($i); 
    } 
} 

這將允許你這樣做

$arr = array(7, 8, 9, 10, 11, 12, 13); 
$matches = array_filter($arr, new LowerThanFilter(12)); 
print_r($matches); 
5
class ArraySearcher{ 

const OPERATOR_EQUALS = '=='; 
const OPERATOR_GREATERTHAN = '>'; 
const OPERATOR_LOWERTHAN = '<'; 
const OPERATOR_NOT = '!=';  

private $_field; 
private $_operation; 
private $_val; 

public function __construct($field,$operation,$num) { 
    $this->_field = $field; 
    $this->_operation = $operation; 
    $this->_val = $num; 
} 


function __invoke($i) { 
    switch($this->_operation){ 
     case '==': 
      return $i[$this->_field] == $this->_val; 
     break; 

     case '>': 
      return $i[$this->_field] > $this->_val; 
     break; 

     case '<': 
      return $i[$this->_field] < $this->_val; 
     break; 

     case '!=': 
      return $i[$this->_field] != $this->_val; 
     break; 
    } 
} 


} 

這使您可以在多維數組篩選項目:如果您在使用PHP 5.3及以上

$users = array(); 
$users[] = array('email' => '[email protected]','name' => 'Robert'); 
$users[] = array('email' => '[email protected]','name' => 'Carl'); 
$users[] = array('email' => '[email protected]','name' => 'Robert'); 

//Print all users called 'Robert' 
print_r(array_filter($users, new ArraySearcher('name',ArraySearcher::OPERATOR_EQUALS,'Robert'))); 
160

,你可以用closure來簡化你的代碼:

$NUM = 5; 
$items = array(1, 4, 5, 8, 0, 6); 
$filteredItems = array_filter($items, function($elem) use($NUM){ 
    return $elem < $NUM; 
}); 
+9

不知道你可以使用'use'這個詞來爲lambda提供額外的參數。感謝這樣一個有價值的提示! :) – 2013-09-24 10:31:22

+9

這在我看來是最好的解決方案。這很簡單,重點突出。很遺憾PHP不允許匿名函數使用父範圍中聲明的變量,就像在javascript中一樣。 – NadiaFaya 2013-09-24 15:08:50

+2

有用,優雅,簡短,+1 – Boog 2015-01-14 09:13:45

9

如果需要多個參數傳遞給函數,你可以將它們添加到使用使用聲明「」:

$r = array_filter($anArray, function($anElement) use ($a, $b, $c){ 
    //function body where you may use $anElement, $a, $b and $c 
});