34

I'm looking for an array function that does something like this:

$myArray = array(
  'apple'=>'red',
  'banana'=>'yellow',
  'lettuce'=>'green',
  'strawberry'=>'red',
  'tomato'=>'red'
);
$keys = array(
  'lettuce',
  'tomato'
);

$ret = sub_array($myArray, $keys);

where $ret is:

array(
  'lettuce'=>'green',
  'tomato'=>'red'
);

A have no problem in writing it down by myself, the thing is I would like to avoid foreach loop and adopt a built-in function or a combination of built-in functions. It seems to me like a general and common array operation - I'd be surprised if a loop is the only option.

3

4 Answers 4

58

This works:

function sub_array(array $haystack, array $needle)
{
    return array_intersect_key($haystack, array_flip($needle));
}

$myArray = array(
    'apple'=>'red',
    'banana'=>'yellow',
    'lettuce'=>'green',
    'strawberry'=>'red',
    'tomato'=>'red'
);
$keys = array(
    'lettuce',
    'tomato'
);

$ret = sub_array($myArray, $keys);

var_dump($ret);
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks. New to php and coming from R where subsetting is done in a breeze, I was slowly starting to pull my hairs out. This saved my scalp ;) If I could give you +10 I would, gladly.
@Joel.O you can add a bounty to the question, and award it.
This should be an internal PHP Array function.
8

You can use array_intersect_key, but it uses second array with keys and values. It computes the intersection of arrays using keys for comparison

array_intersect_key

<?php
$array1 = array('blue'  => 1, 'red'  => 2, 'green'  => 3, 'purple' => 4);
$array2 = array('green' => 5, 'blue' => 6, 'yellow' => 7, 'cyan'   => 8);
$array3 = array('green' => '', 'blue' => '', 'yellow' => '', 'cyan' => '');
$array4 = array('green', 'blue', 'yellow', 'cyan');

var_dump(array_intersect_key($array1, $array2));
var_dump(array_intersect_key($array1, $array3));
var_dump(array_intersect_key($array1, $array4));
?>

The above example will output:

array(2) {
  ["blue"]=>
  int(1)
  ["green"]=>
  int(3)
}

array(2) {
  ["blue"]=>
  int(1)
  ["green"]=>
  int(3)
}

array(0) {
}

1 Comment

How is this the accepted answer? Simple fix as per @Maciej's answer: array_intersect_key($array1, array_flip($array4));
0
    $ret = array_filter($myArray, function ($key) use ($keys) {
        return in_array($key, $keys);
    }, ARRAY_FILTER_USE_KEY);

1 Comment

Note: This may not return the result you are expecting, because the $keys variable is external to the anonymous function. Please check the use keyword -- as described in this stackoverflow post: stackoverflow.com/a/8403958/42223
0

One-liner:

$subArray = array_intersect_key($items, array_fill_keys($keys, 1));

Example:

<?php
$items = [ 'product_id' => 1234, 'color' => 'green', 'qty' => 5, 'desc' => 'Shirt' ];
$keys = [ 'product_id', 'desc' ];
$subArray = array_intersect_key($items, array_fill_keys($keys, 1));
var_dump($subArray);

Produces:

array(2) {
  ["product_id"]=>
  int(1234)
  ["desc"]=>
  string(5) "Shirt"
}

Works with:

  • numerical keys,
  • associative arrays,
  • mixed arrays,
  • arrays with non-unique values

1 Comment

Thank you, matt from the past.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.