PHP array_filter带参数

问题描述:

我有以下代码: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或任何数字?

作为替代@查尔斯的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

在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 2011-03-30 17:40:31

+3

'create_function()'基本上是'eval()'与另一个名字,并且同样邪恶。使用它应该是不鼓励的。在接受的答案中给出的古怪的基于类的解决方法比在这种情况下使用'create_function()'更好的解决方案。 – Charles 2011-03-30 17:43:26

在扩展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); 

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'))); 

,你可以用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

如果需要多个参数传递给函数,你可以将它们添加到使用使用声明“”:

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