If you want an array that has no key value pairs added from the second array:
$new = array_intersect_key($b, $a) + $a;
(PHP 5 >= 5.1.0, PHP 7, PHP 8)
array_intersect_key — 使用键名比较计算数组的交集
$array
, array ...$arrays
) : array
array_intersect_key() 返回一个数组,该数组包含了所有出现在
array
和其它参数数组中同时存在的键名的值。
array
要检查的数组,作为主值。
arrays
要被对比的数组。
返回一个关联数组,该数组包含了所有出现在
array
和其它参数数组中同时存在的键名的值。
Example #1 array_intersect_key() 例子
<?php
$array1 = array('blue' => 1, 'red' => 2, 'green' => 3, 'purple' => 4);
$array2 = array('green' => 5, 'blue' => 6, 'yellow' => 7, 'cyan' => 8);
var_dump(array_intersect_key($array1, $array2));
?>
以上例程会输出:
array(2) { ["blue"]=> int(1) ["green"]=> int(3) }
上例中可以看到,只有 'blue'
和 'green'
两个键名同时出现在两个数组中,因此被返回。另外注意
'blue'
和 'green'
的值在两个数组中是不同的。但因为只检查键名,因此还是匹配。返回的只是
array
中的值。
在 key => value
对中的两个键名仅在
(string) $key1 === (string) $key2
时才被认为相等。换句话说,执行了严格的类型检查,因此字符串的表达形式必须相同。
If you want an array that has no key value pairs added from the second array:
$new = array_intersect_key($b, $a) + $a;
[Editor's note: changed array_merge_recursive() to array_replace_recursive() to fix the script]
Here is a better way to merge settings using some defaults as a whitelist.
<?php
$defaults = [
'id' => 123456,
'client_id' => null,
'client_secret' => null,
'options' => [
'trusted' => false,
'active' => false
]
];
$options = [
'client_id' => 789,
'client_secret' => '5ebe2294ecd0e0f08eab7690d2a6ee69',
'client_password' => '5f4dcc3b5aa765d61d8327deb882cf99', // ignored
'client_name' => 'IGNORED', // ignored
'options' => [
'active' => true
]
];
var_dump(
array_replace_recursive($defaults,
array_intersect_key(
$options, $defaults
)
)
);
?>
Output:
array (size=4)
'id' => int 123456
'client_id' => int 789
'client_secret' => string '5ebe2294ecd0e0f08eab7690d2a6ee69' (length=32)
'options' =>
array (size=2)
'trusted' => boolean false
'active' => boolean true
in case you came here looking for a function that returns an array containing the values of `all` arrays with intersecting keys:
<?php
function array_merge_on_key($key, $array1, $array2) {
$arrays = array_slice(func_get_args(), 1);
$r = array();
foreach($arrays as &$a) {
if(array_key_exists($key, $a)) {
$r[] = $a[$key];
continue;
}
}
return $r;
}
// example:
$array1 = array("id" => 12, "name" => "Karl");
$array2 = array("id" => 4, "name" => "Franz");
$array3 = array("id" => 9, "name" => "Helmut");
$array4 = array("id" => 10, "name" => "Kurt");
$result = array_merge_on_key("id", $array1, $array2, $array3, $array4);
echo implode(",", $result); // => 12,4,9,10
?>
Simple key white-list filter:
<?php
$arr = array('a' => 123, 'b' => 213, 'c' => 321);
$allowed = array('b', 'c');
print_r(array_intersect_key($arr, array_flip($allowed)));
?>
Will return:
Array
(
[b] => 213
[c] => 321
)
Note that the order of the keys in the returned array is the same as the order of the keys in the source array. eg:
<?php
$array = array(
'two' => 'a',
'three' => 'b',
'one' => 'c',
);
$keyswant = array(
'one' => '',
'three' => '',
);
print_r(array_intersect_key($array, $keyswant));
?>
Shows:
Array
(
[three] => b
[one] => c
)
Regarding php at keithtylerdotcom solution to emulate
<?php
$z = someFuncReturningAnArray()['some_key'];
?>
His recommended solution will still return an array. To get the value of a single key in an array returned by a function, simply add implode() to the recipe:
<?php
function someFuncReturningAnArray() {
return array(
'a' => 'b',
'c' => 'd',
'e' => 'f',
'g' => 'h',
'i' => 'j'
);
}
//traditional way
$temp = someFuncReturningAnArray();
$b = $temp['a'];
echo print_r($b, 1) . "\n----------\n";
//keithtylerdotcom one-line method
$b = array_intersect_key(someFuncReturningAnArray(), array('a'=>''));
echo print_r($b, 1) . "\n----------\n";
//better one line method
$b = implode('', array_intersect_key(someFuncReturningAnArray(), array('a'=>'')));
echo print_r($b, 1) . "\n----------\n";
?>
<?php
/**
* calculates intersection of two arrays like array_intersect_key but recursive
*
* @param array/mixed master array
* @param array array that has the keys which should be kept in the master array
* @return array/mixed cleand master array
*/
function myIntersect($master, $mask) {
if (!is_array($master)) { return $master; }
foreach ($master as $k=>$v) {
if (!isset($mask[$k])) { unset ($master[$k]); continue; } // remove value from $master if the key is not present in $mask
if (is_array($mask[$k])) { $master[$k] = $this->myIntersect($master[$k], $mask[$k]); } // recurse when mask is an array
// else simply keep value
}
return $master;
}
?>
Just a simple script if you want to use one array, which contains only zeros and ones, as mask for another one (both arrays must have the same size of course). $outcome is an array that contains only those values from $source where $mask is equal to 1.
<?php
$outcome = array_values(array_intersect_key( array_values($source), array_filter(array_values($mask)) ));
?>
PS: the array_values() function is necessary to ensure that both arrays have the same numbering/keys, otherwise your masking does not behave as you expect.
Enjoy!
I have found the following helpful:
<?PHP
function array_merge_default($default, $data) {
$intersect = array_intersect_key($data, $default); //Get data for which a default exists
$diff = array_diff_key($default, $data); //Get defaults which are not present in data
return $diff + $intersect; //Arrays have different keys, return the union of the two
}
?>
It's use is like both of the functions it uses, but keeps defaults and _only_ defaults. It's designed for key arrays, and i'm not sure how it will work on numeric indexed arrays.
Example:
<?PHP
$default = array(
"one" => 1,
"two" => 2
);
$untrusted = array(
"one" => 42,
"three" => 3
);
var_dump(array_merge_default($default, $untrusted));
array(2) {
["two"]=>
int(2)
["one"]=>
int(42)
}
?>
Jesse: no, array_intersect_key does not accomplish the same thing as what you posted:
array_flip (array_intersect (array_flip ($a), array_flip ($b)))
because when the array is flipped, values become keys. having duplicate values is not a problem, but having duplicate keys is. array_flip resolves it by keeping only one of the duplicates and discarding the rest. by the time you start intersecting, you've already lost information.