32

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.

dreftymac
  • 31,404
  • 26
  • 119
  • 182
user1517081
  • 965
  • 2
  • 11
  • 30
  • Duplicate: http://stackoverflow.com/questions/3454993/get-a-subset-of-an-array-based-on-an-array-of-keys – David Hancock Sep 22 '12 at 11:45
  • **See also:** https://stackoverflow.com/questions/13766898/ -- dealing with array_key substrings instead of entire array_keys. – dreftymac Aug 24 '19 at 22:52
  • **See also:** https://underscorejs.org/#pick and https://stackoverflow.com/a/40270589/42223 for how this relates to `higher-order-functions` – dreftymac Aug 24 '19 at 23:11

4 Answers4

55

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);
Maciej Lew
  • 626
  • 6
  • 5
7

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) {
}
Pradeep Sanjaya
  • 1,816
  • 1
  • 15
  • 23
  • How is this the accepted answer? Simple fix as per @Maciej's answer: array_intersect_key($array1, array_flip($array4)); – Brad Kent Jan 29 '16 at 05:26
0
    $ret = array_filter($myArray, function ($key) use ($keys) {
        return in_array($key, $keys);
    }, ARRAY_FILTER_USE_KEY);
Nicolas Dermine
  • 628
  • 5
  • 8
  • 1
    **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: https://stackoverflow.com/a/8403958/42223 – dreftymac Aug 24 '19 at 22:44
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
matt
  • 4,614
  • 1
  • 29
  • 32