PHP array_filter với các đối số


108

Tôi có mã sau:

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

mà tôi có thể sử dụng để lọc một mảng như sau:

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

Làm cách nào để thêm đối số vào Lower_than_10 để nó cũng chấp nhận số để kiểm tra? Giống như, nếu tôi có cái này:

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

làm thế nào để gọi nó từ array_filter chuyển 10 đến $ num hoặc bất kỳ số nào?

Câu trả lời:


64

Là một giải pháp thay thế cho giải pháp của @ Charles bằng cách sử dụng các bao đóng , bạn thực sự có thể tìm thấy một ví dụ trong các nhận xét trên trang tài liệu. Ý tưởng là bạn tạo một đối tượng với trạng thái mong muốn ( $num) và phương thức gọi lại (lấy $ilàm đối số):

class LowerThanFilter {
        private $num;

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

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

Cách sử dụng ( demo ):

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

Là một sidenote, bây giờ bạn có thể thay thế LowerThanFiltervới một chung chung hơn NumericComparisonFiltervới các phương pháp như isLower, isGreater, isEqualvv Chỉ cần một ý nghĩ - và một bản demo ...


Cách giải quyết tốt. Vì lợi ích của mã có thể bảo trì, nó có thể giúp sửa đổi lớp để hỗ trợ các lệnh gọi phương thức dễ đọc hơn: $ match = $ myobj-> ArraySelect (Array ('from' => $ arr, 'where' => $ foo, 'lessthan' => 12))
dreftymac 10/11/11

Tôi không phải là người hiểu biết về php, vì vậy có thể đây là một câu hỏi hiển nhiên, nhưng làm thế nào bạn có thể chuyển một mảng vào array_filter và vẫn làm cho nó hoạt động? tài liệu không bao giờ nói về điều này, ngoại trừ nhận xét của ai đó.
Nicola Pedretti

1
@NicolaPedretti Tôi cho rằng bạn đang nói về đối số giây array_filter? Nó chỉ đơn giản là một callable; trong trường hợp trên so khớp "Loại 3: Cuộc gọi phương thức đối tượng" array(<instance>, <method-name>):, cf. PHP: Callbacks / Callables - Thủ công .
jensgram

Hấp dẫn. Nó thực sự cảm thấy khó khăn với tôi. Truyền phương pháp trực tiếp có vẻ trực quan hơn.
Nicola Pedretti

@nicolapedretti Tôi đã không đụng đến PHP trong vài năm. Bởi bây giờ hầu hết nó cảm thấy hacky với tôi :)
jensgram

260

nếu bạn đang sử dụng php 5.3 trở lên, bạn có thể sử dụng hàm đóng để đơn giản hóa mã của mình:

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

12
Không biết rằng bạn có thể sử dụng usetừ này để cung cấp cho lambda các tham số bổ sung. Cảm ơn vì một gợi ý có giá trị như vậy! :)
Julio María Meca Hansen

15
Theo tôi đây là giải pháp tốt nhất. Nó đơn giản và đến mức. Thật tiếc khi PHP không cho phép các hàm ẩn danh sử dụng các biến được khai báo trong phạm vi mẹ, như trong javascript.
NadiaFaya 24/09/13

4
Hữu ích, thanh lịch, ngắn, 1
grokking

7
Tôi tin rằng đây phải là giải pháp được chấp nhận, vì nó là giải pháp duy nhất trả lời câu hỏi: "làm thế nào có thể thêm đối số vào array_filter" . Các câu trả lời khác là cung cấp các tuyến đường thay thế cho cùng một kết quả, sử dụng bao đóng hoặc các lớp.
tao

Cảm ơn anh bạn. Hoàn hảo
Arunjith RS

36

Trong PHP 5.3 trở lên, bạn có thể sử dụng một bao đóng :

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
thanks cho các giải pháp, nó là gọn gàng, nhưng tôi có php 5.2 trên máy chủ, vì vậy tôi buộc phải sử dụng jensgram của :)
pistacchio

Trong php <5.3, bạn có thể sử dụng create_function().
Decent Dabbler,

3
create_function()về cơ bản là eval()với một tên khác, và cũng ác. Sử dụng nó nên được khuyến khích. Cách giải quyết dựa trên lớp lập dị được đưa ra trong câu trả lời được chấp nhận là một giải pháp tốt hơn là sử dụng create_function()trong trường hợp này.
Charles

20

nếu bạn cần nhiều tham số được truyền vào hàm, bạn có thể thêm chúng vào câu lệnh sử dụng bằng cách sử dụng ",":

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

14

Trong phần mở rộng cho câu trả lời jensgram, bạn có thể thêm một số phép thuật khác bằng cách sử dụng __invoke()phương pháp ma thuật.

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

Điều này sẽ cho phép bạn làm

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


}

Điều này cho phép bạn lọc các mục trong các mảng đa chiều:

$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')) );
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.