PHP: How to use array_filter() to filter array key

2019-01-01 05:58发布

The callback function in array_filter() only passes in the array's values, not the keys.

If I have:

$my_array = array("foo" => 1, "hello" => "world");

$allowed = array("foo", "bar");

What's the best way to delete all keys in $my_array that are not in the $allowed array?

Desired output:

$my_array = array("foo" => 1);

标签: php arrays
13条回答
临风纵饮
2楼-- · 2019-01-01 06:49
$elements_array = ['first', 'second'];

function to remove some array elements

function remove($arr, $data) {
    return array_filter($arr, function ($element) use ($data) {
        return $element != $data;
    });
}

call and print

print_r(remove($elements_array, 'second'));

the result Array ( [0] => first )

查看更多
萌妹纸的霸气范
3楼-- · 2019-01-01 06:51

array filter function from php:

array_filter ( $array, $callback_function, $flag )

$array - It is the input array

$callback_function - The callback function to use, If the callback function returns true, the current value from array is returned into the result array.

$flag - It is optional parameter, it will determine what arguments are sent to callback function. If this parameter empty then callback function will take array values as argument. If you want to send array key as argument then use $flag as ARRAY_FILTER_USE_KEY. If you want to send both keys and values you should use $flag as ARRAY_FILTER_USE_BOTH .

For Example : Consider simple array

$array = array("a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>5);

If you want to filter array based on the array key, We need to use ARRAY_FILTER_USE_KEY as third parameter of array function array_filter.

$get_key_res = array_filter($array,"get_key",ARRAY_FILTER_USE_KEY );

If you want to filter array based on the array key and array value, We need to use ARRAY_FILTER_USE_BOTH as third parameter of array function array_filter.

$get_both = array_filter($array,"get_both",ARRAY_FILTER_USE_BOTH );

Sample Callback functions:

 function get_key($key)
 {
    if($key == 'a')
    {
        return true;
    } else {
        return false;
    }
}
function get_both($val,$key)
{
    if($key == 'a' && $val == 1)
    {
        return true;
    }   else {
        return false;
    }
}

It will output

Output of $get_key is :Array ( [a] => 1 ) 
Output of $get_both is :Array ( [a] => 1 ) 
查看更多
忆尘夕之涩
4楼-- · 2019-01-01 06:55

PHP 5.6 introduced a third parameter to array_filter(), flag, that you can set to ARRAY_FILTER_USE_KEY to filter by key instead of value:

$my_array = ['foo' => 1, 'hello' => 'world'];
$allowed  = ['foo', 'bar'];
$filtered = array_filter(
    $my_array,
    function ($key) use ($allowed) {
        return in_array($key, $allowed);
    },
    ARRAY_FILTER_USE_KEY
);

Clearly this isn't as elegant as array_intersect_key($my_array, array_flip($allowed)), but it does offer the additional flexibility of performing an arbitrary test against the key, e.g. $allowed could contain regex patterns instead of plain strings.

You can also use ARRAY_FILTER_USE_BOTH to have both the value and the key passed to your filter function. Here's a contrived example based upon the first, but note that I'd not recommend encoding filtering rules using $allowed this way:

$my_array = ['foo' => 1, 'bar' => 'baz', 'hello' => 'wld'];
$allowed  = ['foo' => true, 'bar' => true, 'hello' => 'world'];
$filtered = array_filter(
    $my_array,
    function ($val, $key) use ($allowed) { // N.b. $val, $key not $key, $val
        return isset($allowed[$key]) && (
            $allowed[$key] === true || $allowed[$key] === $val
        );
    },
    ARRAY_FILTER_USE_BOTH
); // ['foo' => 1, 'bar' => 'baz']
查看更多
孤独总比滥情好
5楼-- · 2019-01-01 06:57

Perhaps an overkill if you need it just once, but you can use YaLinqo library* to filter collections (and perform any other transformations). This library allows peforming SQL-like queries on objects with fluent syntax. Its where function accepts a calback with two arguments: a value and a key. For example:

$filtered = from($array)
    ->where(function ($v, $k) use ($allowed) {
        return in_array($k, $allowed);
    })
    ->toArray();

(The where function returns an iterator, so if you only need to iterate with foreach over the resulting sequence once, ->toArray() can be removed.)

* developed by me

查看更多
泪湿衣
6楼-- · 2019-01-01 06:59

Here is a more flexible solution using a closure:

$my_array = array("foo" => 1, "hello" => "world");
$allowed = array("foo", "bar");
$result = array_flip(array_filter(array_flip($my_array), function ($key) use ($allowed)
{
    return in_array($key, $allowed);
}));
var_dump($result);

Outputs:

array(1) {
  'foo' =>
  int(1)
}

So in the function, you can do other specific tests.

查看更多
刘海飞了
7楼-- · 2019-01-01 07:04

With array_intersect_key and array_flip:

var_dump(array_intersect_key($my_array, array_flip($allowed)));

array(1) {
  ["foo"]=>
  int(1)
}
查看更多
登录 后发表回答