Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

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);
share|improve this question

4 Answers

up vote 94 down vote accepted

With array_intersect_key and array_flip:

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

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

array_intersect_key is pretty much self explanatory and array_flip flips the keys with the values.

share|improve this answer
1  
That's clever, I never thought to use array_flip – GWW Nov 23 '10 at 19:47
+1 for array_flip, you beat me to it. :) – netcoder Nov 23 '10 at 19:47
I'm curious if this is more efficient than my solution though? It's definitely more elegant :) – GWW Nov 23 '10 at 19:48
2  
gorgeous. thank you, @Vincent Savard – maček Nov 23 '10 at 19:53
3  
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) – Matthew Nov 23 '10 at 19:53
show 7 more comments

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

Here's how I did it, using a similar method.

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

This outputs the result:

Array
(
    [three] => val three
    [four] => val four
    [five] => val five
)
share|improve this answer
exactly what i needed :) – nico roy Nov 30 '12 at 20:29

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.

share|improve this answer
I wouldn't exactly call this "more flexible"; it feels a lot less straightforward than the accepted solution, too. – maček Jan 26 at 21:33
I agree. It would be more flexible is the condition was a more complex one. – COil Jan 31 at 11:25

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

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

The result of print_r($array) being:

Array
(
    [2] => two
)

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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.