Rectangle 27 1

PHP: How to use array_filter() to filter array keys?


$apples = array_filter($array, function($color) use ($&array) {
  return each($array)['key'] === 'apple';
}
$array = ['apple' => 'red', 'pear' => 'green'];
reset($array); // Unimportant here, but make sure your array is reset

$apples = array_filter($array, function($color) use ($&array) {
  $key = key($array);
  next($array); // advance array pointer

  return key($array) === 'apple';
}

In PHP >= 5.4 you could make the callback even shorter:

It passes the array you're filtering as a reference to the callback. As array_filter doesn't conventionally iterate over the array by increasing it's public internal pointer you have to advance it by yourself.

Regardless of how I like Vincent's solution for maek's problem, if you came here from a search engine you maybe where looking for something like this (PHP >= 5.3):

What's important here is that you need to make sure your array is reset, otherwise you might start right in the middle of it.

Note
Rectangle 27 1

PHP: How to use array_filter() to filter array keys?


$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);
array(1) {
  'foo' =>
  int(1)
}

Here is a more flexible solution using a closure:

I agree this is more flexible as it allows you to change the filter logic. For example I used an array of disallowed keys and simply returned !in_array($key, $disallowed).

I wouldn't exactly call this "more flexible"; it feels a lot less straightforward than the accepted solution, too.

Just passing by, for other users: This solution does not deal with the case that the $my_array has duplicate values or values that are not integers or strings. So I would not use this solution.

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

Note
Rectangle 27 1

PHP: How to use array_filter() to filter array keys?


$mArray=array('foo'=>'bar','foo2'=>'bar2','fooToo'=>'bar3','baz'=>'nope');
$mSearch='foo';
$allowed=array_filter(
    array_keys($mArray),
    function($key) use ($mSearch){
        return stristr($key,$mSearch);
    });
$mResult=array_intersect_key($mArray,array_flip($allowed));
Array
(
    [foo] => yes
    [foo2] => yes
    [FooToo] => yes
)
Array ( [foo] => bar [foo2] => bar2 [fooToo] => bar3 )
function array_preg_filter_keys($arr, $regexp) {
  $keys = array_keys($arr);
  $match = array_filter($keys, function($k) use($regexp) {
    return preg_match($regexp, $k) === 1;
  });
  return array_intersect_key($arr, array_flip($match));
}

$mArray = array('foo'=>'yes', 'foo2'=>'yes', 'FooToo'=>'yes', 'baz'=>'nope');

print_r(array_preg_filter_keys($mArray, "/^foo/i"));
print_r($mResult)

If you are looking for a method to filter an array by a string occurring in keys, you can use:

You are certainly right, maek, that is a more versatile approach for users who are comfortable with regex. Thanks.

thanks for your answer. I would submit to you that using stristr within the "work" of the function is making some assumptions for the end user. Perhaps it would be better to allow the user to pass in a regular expression; this would give them more flexibility over certain things like anchors, word boundaries, and case sensitivity, etc.

Note
Rectangle 27 1

PHP: How to use array_filter() to filter array keys?


$allowed
allowed = array ( 'foo' => 1, 'bar' => 1 );
array_flip
array_intersect_key
var_dump(array_intersect_key($my_array, array_flip($allowed)));

array(1) {
  ["foo"]=>
  int(1)
}

This is not a general solution because it would mandate that each value is unique. Edit: sorry.. I misread the solution. Flipping on the allowed keys is a good solution (+1)

Note
Rectangle 27 1

PHP: How to use array_filter() to filter array keys?


$array = array(
    1 => 'one',
    2 => 'two',
    3 => 'three'
);
$disallowed = array(1,3);
foreach($disallowed as $key){
    unset($array[$key]);
}
Array
(
    [2] => two
)
print_r($array)

@JarekJakubowski you do not need to check if an array key exists when using unset(). No warnings are issued if the key doesn't exist.

Here's a less flexible alternative using unset():

This is not applicable if you want to keep the filtered values for later use but tidier, if you're certain that you don't.

You should check if key $key exists in $array before doing unset.

Note
Rectangle 27 1

PHP: How to use array_filter() to filter array keys?


$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']
$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
);
5.6
array_intersect

@Jack Ha ha! Well, thanks; it's clearly a useful feature!

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.

Damn, as the author of that feature I should have looked for this question ;-)

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:

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:

Note
Rectangle 27 1

PHP: How to use array_filter() to filter array keys?


// Filter out array elements with keys shorter than 4 characters
$a = array(
  0      => "val 0", 
  "one"  => "val one", 
  "two"  => "val two", 
  "three"=> "val three", 
  "four" => "val four", 
  "five" => "val five", 
  "6"    => "val 6"
); 

$f = array_filter(array_keys($a), function ($k){ return strlen($k)>=4; }); 
$b = array_intersect_key($a, array_flip($f));
print_r($b);
Array
(
    [three] => val three
    [four] => val four
    [five] => val five
)

I needed to do same, but with a more complex array_filter on the keys.

This made me leak very slightly- very nice bit of PHPing. +1

Note
Rectangle 27 1

PHP: How to use array_filter() to filter array keys?


$apples = array_filter($array, function($color) use ($&array) {
  return each($array)['key'] === 'apple';
}
$array = ['apple' => 'red', 'pear' => 'green'];
reset($array); // Unimportant here, but make sure your array is reset

$apples = array_filter($array, function($color) use ($&array) {
  $key = key($array);
  next($array); // advance array pointer

  return key($array) === 'apple';
}

In PHP >= 5.4 you could make the callback even shorter:

It passes the array you're filtering as a reference to the callback. As array_filter doesn't conventionally iterate over the array by increasing it's public internal pointer you have to advance it by yourself.

Regardless of how I like Vincent's solution for Maek's problem, it doesn't actually use array_filter. If you came here from a search engine you maybe where looking for something like this (PHP >= 5.3):

What's important here is that you need to make sure your array is reset, otherwise you might start right in the middle of it.

Note
Rectangle 27 1

PHP: How to use array_filter() to filter array keys?


$result = [];
foreach ($my_array as $key => $value) {
    if (in_array($key, $allowed)) {
        $result[$key] = $value;
    }
}
$result = array_filter($my_array, function ($k) use ($allowed) {
    return in_array($k, $allowed);
}, ARRAY_FILTER_USE_KEY);
function filter_array_keys(array $array, $keys)
{
    if (is_callable($keys)) {
        $keys = array_filter(array_keys($array), $keys);
    }

    return array_intersect_key($array, array_flip($keys));
}

// using a callback, like array_filter:
$result = filter_array_keys($my_array, function ($k) use ($allowed) {
    return in_array($k, $allowed);
});

// or, if you already have the keys:
$result = filter_array_keys($my_array, $allowed));

And here is an augmented version of mine, which accepts a callback or directly the keys:

Last but not least, you may also use a simple foreach:

Otherwise, you can use this function (from TestDummy):

Starting from PHP 5.6, you can use the ARRAY_FILTER_USE_KEY flag in array_filter:

Note
Rectangle 27 1

PHP: How to use array_filter() to filter array keys?


$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.)

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:

Note