PHP array_filter与参数


108

我有以下代码:

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或任何数字?

Answers:


64

作为@Charles使用闭包解决方案的替代方法,您实际上可以在文档页面的注释中找到示例。这个想法是您创建一个具有所需状态($num)和回调方法($i作为参数)的对象:

class LowerThanFilter {
        private $num;

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

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

用法(演示):

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

作为一个旁注,你现在可以更换LowerThanFilter一个更通用的NumericComparisonFilter用类似的方法isLowerisGreaterisEqual等只是一个想法-和演示 ...


好的解决方法。为了使代码易于维护,可能还需要修改该类以支持更具可读性的方法调用:$ matches = $ myobj-> ArraySelect(Array('from'=> $ arr,'where'=> $ foo, 'lessthan'=> 12))
dreftymac

我不是php精明的人,所以也许这是一个显而易见的问题,但是如何将数组传递给array_filter并使其仍然有效?除了有人的评论外,文档从未讨论过。
Nicola Pedretti

1
@NicolaPedretti我想你是在说秒参数array_filter?这简直是callable;在上述情况下,匹配“类型3:对象方法调用”:array(<instance>, <method-name>),请参见。PHP:回调/可调用对象-手册
jensgram '17

有趣。对我来说确实感觉很hacky。直接传递方法似乎更直观。
Nicola Pedretti

@nicolapedretti我已经好几年没有接触PHP了。到现在为止,大多数感觉对我来说都是很
拙劣的

260

如果您使用的是php 5.3及更高版本,则可以使用闭包来简化代码:

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

12
不知道您可以使用use单词为lambda提供额外的参数。感谢您提供如此宝贵的提示!:)
JulioMaríaMeca Hansen

15
我认为这是最好的解决方案。简单明了。令人遗憾的是,PHP不允许匿名函数使用在父作用域中声明的变量(例如在javascript中)。
NadiaFaya

4
有用,优雅,简短的+1
Grokking 2015年

7
我认为这应该是公认的解决方案,因为它是回答问题的唯一方法:“如何向array_filter添加参数”。其他答案是使用闭包或类为相同的结果提供替代路线。
tao 2015年

多谢,伙计。完美
Arunjith RS

36

在PHP 5.3或更高版本中,可以使用闭包

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的:)
pistacchio

在php <5.3中,您可以使用create_function()
体面的达伯勒

3
create_function()基本上eval()是另一个名字,也一样邪恶。不鼓励使用它。比create_function()在这种情况下使用的更好,基于接受的答案的基于类的变通方法是一个更好的解决方案。
查尔斯

20

如果需要将多个参数传递给函数,则可以使用“,”将它们附加到use语句中:

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

14

在延拓答案的扩展中,您可以使用__invoke()magic方法添加更多魔术。

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;
    }
}


}

这使您可以过滤多维数组中的项目:

$users = array();
$users[] = array('email' => 'user1@email.com','name' => 'Robert');
$users[] = array('email' => 'user2@email.com','name' => 'Carl');
$users[] = array('email' => 'user3@email.com','name' => 'Robert');

//Print all users called 'Robert'
print_r( array_filter($users, new ArraySearcher('name',ArraySearcher::OPERATOR_EQUALS,'Robert')) );
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.