With array_intersect_key and array_flip:
var_dump(array_intersect_key($my_array, array_flip($allowed)));
array(1) {
["foo"]=>
int(1)
}
Answer from Vincent Savard on Stack OverflowWith array_intersect_key and array_flip:
var_dump(array_intersect_key($my_array, array_flip($allowed)));
array(1) {
["foo"]=>
int(1)
}
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 (
allowed) {
// N.b. in_array() is notorious for being slow
return in_array(
allowed);
},
ARRAY_FILTER_USE_KEY
);
Since PHP 7.4 introduced arrow functions we can make this more succinct:
$my_array = ['foo' => 1, 'hello' => 'world'];
$allowed = ['foo', 'bar'];
$filtered = array_filter(
$my_array,
fn ($key) => in_array(
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,
fn (
key) => isset($allowed[$key]) && (
$allowed[$key] === true || $allowed[
val
),
ARRAY_FILTER_USE_BOTH
); // ['foo' => 1, 'bar' => 'baz']
Videos
I always believe that you should use built in functions wherever possible, as opposed to recreating PHP functionality with loops etc. The main reasons for saying this are that:
- We should trust that PHP functions achieve their desired result in an efficient manner, and:
- If they are improved in future versions your code doesn't need to change, but just gets better.
That being said, why not something like this:
$matches = array_intersect_key($langs, array_flip($allowed_langs));
var_export($matches);
I find your solution rather complicated, so I would prefer this one:
foreach ($langs as $k => $v) {
if (in_array($k, $allowed_langs)) {
$result[$k] = $v;
}
}
var_export($result);
I' m incertain of which one is faster (and I tend to think this shouldn't be really important here), but I'm sure it's more simple and readable.
If I have an array of things, and I filter them so I end up with an array of a single thing from the original things, the index of that thing is what it was in the original array. Why is that? That seems like odd behavior.
Eg. the below code only works if the item I'm filtering for was the 0th item in arrays. I know I can use array_values() to reset the indices of the filtered array, but I'm just wondering why this is a thing
$items = [
'stick',
'ball',
'bat',
'computer'
];
$filtered = array_filter($items, function($item) {
return $item == 'bat';
});
var_dump($filtered[0]); // I need to use the original index from $items in order for this to work; can't always use 0