【问题标题】:PHP array_filter with argumentsPHP array_filter 带参数
【发布时间】:2011-07-25 21:00:52
【问题描述】:

我有以下代码:

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

【问题讨论】:

    标签: php arrays


    【解决方案1】:

    如果你使用 php 5.3 及以上版本,你可以使用closure 来简化你的代码:

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

    【讨论】:

    • 不知道您可以使用 use 词为 lambda 提供额外参数。感谢您提供如此宝贵的提示! :)
    • 我认为这是最好的解决方案。这很简单,也很重要。遗憾的是 PHP 不允许匿名函数使用在父作用域中声明的变量,就像在 javascript 中一样。
    • 实用、优雅、简短、+1
    • 我相信这应该是公认的解决方案,因为它是唯一回答以下问题的解决方案:“如何向 array_filter 添加参数”。其他答案是使用闭包或类为相同结果提供替代路线。
    • 谢谢老兄。完美
    【解决方案2】:

    作为@Charles 的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);
    

    作为旁注,您现在可以将LowerThanFilter 替换为更通用的NumericComparisonFilter,使用isLowerisGreaterisEqual 等方法。只是一个想法——还有一个demo...

    【讨论】:

    • 很好的解决方法。为了代码的可维护性,修改类以支持更易读的方法调用可能会有所帮助: $matches = $myobj->ArraySelect( Array('from'=>$arr, 'where'=>$foo, '小于'=>12 ) )
    • 我不是 php 专家,所以这可能是一个显而易见的问题,但是如何将数组传递给 array_filter 并使其仍然有效?除了某人的评论,文档从不谈论这个。
    • @NicolaPedretti 我假设您正在谈论 array_filter 的 seconds 参数?这只是一个callable;在上述情况下匹配“类型 3:对象方法调用”:array(&lt;instance&gt;, &lt;method-name&gt;),参见。 PHP: Callbacks / Callables - Manual.
    • 有趣。对我来说确实感觉很hacky。直接传递方法似乎更直观。
    • @nicolapedretti 我已经好几年没接触 PHP 了。到现在为止,大部分对我来说都是 hacky :)
    【解决方案3】:

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

    【讨论】:

    • 感谢您的解决方案,它很简洁,但我的服务器上有 php 5.2,所以我一定要使用 jensgram 的 :)
    • 在 php create_function()。
    • create_function() 基本上是 eval() 的另一个名字,同样邪恶。不鼓励使用它。接受的答案中给出的古怪的基于类的解决方法比在这种情况下使用create_function() 更好。
    【解决方案4】:

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

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

    【讨论】:

      【解决方案5】:

      作为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);
      

      【讨论】:

        【解决方案6】:
        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')) );
        

        【讨论】:

          【解决方案7】:

          值得注意的是,由于 PHP 7.4 arrow functions 可用,并且可以更巧妙地完成:

          $max = 10;
          $arr = array(7, 8, 9, 10, 11, 12, 13);
          $new_arr = array_filter($arr, fn ($n) => $n < $max);
          

          【讨论】:

            猜你喜欢
            • 2014-09-21
            • 2018-11-10
            • 1970-01-01
            • 2021-10-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-02-01
            • 1970-01-01
            相关资源
            最近更新 更多