I have 2 arrays:
$array1 = ["b" => "no", "c" => "no", "d" => ["y" => "no"]];
$array2 = ["a" => "yes", "b" => "yes", "c" => "yes", "d" => ["x" => "yes", "y" => "yes", "z" => "yes"]];
I want to return the members of $array2 whose keys are also present in $array1.
Desired output:
$array3 = ["b" => "yes", "c" => "yes", "d" => ["y" => "yes"]];
Basically I need the same functionality as array_intersect_key but I want to keep the values from $array2 instead of $array1.
Does such a function exist? Also needs to recurse into child arrays. Thanks!
*Edit*
As Andri suggested in his comment, I attempted to flip the arguments around array_intersect_key($array2, $array1) but in that case what I actually get is:
$array3 = ["b" => "yes", "c" => "yes", "d" => ["x" => "yes", "y" => "yes", "z" => "yes"]];
ie all the children of "d" just because "d" is mentioned in $array1.
There isn't as far as I'm aware a built in function, a method using recursion to process all layers should be easy enough...
$array1 = ["b" => "no", "c" => "no", "d" => ["y" => "no"]];
$array2 = ["a" => "yes", "b" => "yes", "c" => "yes", "d" => ["x" => "yes", "y" => "yes", "z" => "yes"]];
function intersect_key_2 ( array $a1, array $a2 ) {
foreach ( $a1 as $key1 => $value1) {
// If there is a matching element
if ( isset($a2[$key1]) ) {
// Update - if an array, use recursive call else just replace
$a1[$key1] = ( is_array($value1) ) ? intersect_key_2 ( $value1, $a2[$key1])
: $a2[$key1];
}
}
return $a1;
}
print_r(intersect_key_2($array1, $array2));
gives
Array
(
[b] => yes
[c] => yes
[d] => Array
(
[y] => yes
)
)
Ended up writing my own:
function array_intersect_key_values_2($array1, $array2) : array {
$intersection = [];
foreach ($array1 as $key => $value) {
if(isset($array2[$key]))
{
if(is_array($array1[$key]) && is_array($array2[$key]))
{
$intersection[$key] = array_intersect_key_values_2($array1[$key], $array2[$key]);
}
else
{
$intersection[$key] = $array2[$key];
}
}
}
return($intersection);
}
Related
i have an array like this
Array
(
[zero] => 0
[one] => 1
[two] => 2
[three] => 3
)
I made several keys for exceptions that would be unset (zero and two).
I also got this code in another sources but it doesn't apply if I add a symbol !
$r = ["zero" => 0, "one" => 1, "two" => 2, "three" => 3];
$dontRemove = array('zero','two');
$r = array_diff_key($r, array_flip($dontRemove));
result is
Array
(
[one] => 1
[three] => 3
)
result i want is to unset keys one and three, like this
Array
(
[zero] => 0
[two] => 2
)
$r = ["zero" => 0, "one" => 1, "two" => 2, "three" => 3];
$dontRemove = array($r['zero'],$r['two']);
$r = array_intersect($r, $dontRemove);
print_r($r);
Array
(
[zero] => 0
[two] => 2
)
I think you can solve it from here?
Another option is array_filter:
$r = ["zero" => 0, "one" => 1, "two" => 2, "three" => 3];
$dontRemove = array('zero','two');
print_r(array_filter(
$r,
function($k) use ($dontRemove) { return in_array($k, $dontRemove); },
ARRAY_FILTER_USE_KEY
));
yet another option, not using function(s) - $result contains the desired outcome:
$filter = ['zero', 'two'];
foreach($array as $akey => $aval) {
foreach($filter as $fkey => $fval) {
if($akey === $fval) $result[$akey] = $aval;
}
}
In PHP we do have function array_flip for exchanging all keys with their associated values in an array, however I am looking for a the solution as follows with the help of php functions
INPUT
array(
"a" => 1,
"b" => 1,
"c" => 2
);
OUTPUT
array(
1 => array("a", "b"),
2 => "c"
);
I don't think there is a php function for it, so you'll have to write your own. If you really want a mixture of nested arrays and values the way to go would be:
function my_array_flip($arr)
{
$new_arr = array();
foreach ($arr as $k => $v)
{
if (array_key_exists($v, $new_arr))
{
if (is_array($new_arr[$v]))
{
$new_arr[] = $k;
}
else
{
$new_arr[$v] = array($new_arr[$v]);
$new_arr[$v][] = $k;
}
}
else
{
$new_arr[$v] = $k;
}
}
return $new_arr;
}
For your array this will return:
Array
(
[1] => Array
(
[0] => a
[1] => b
)
[2] => c
)
$source = array(
"a" => 1,
"b" => 1,
"c" => 2
);
foreach ($source as $key => $value)
{
$result[$value][] = $key;
}
Don't think exists a function for that but you can achieve it with some code:
$input = [
"a" => 1,
"b" => 1,
"c" => 2,
];
$grouped = [];
foreach ($input as $key => $group) {
$grouped[$group][] = $key;
}
Result:
var_dump($grouped);
array(2) {
[1] =>
array(2) {
[0] =>
string(1) "a"
[1] =>
string(1) "b"
}
[2] =>
array(1) {
[0] =>
string(1) "c"
}
}
Sets always array as values because I guess this will simplify things when you'll use the result in your code.
A have a php array
$arr = array(
1 => "a",
2 => "b",
4 => "c",
8 => "d",
16 => "e",
32 => "f"
);
and a binary number
$filter=101101
I want to filter the array and keep only the keys where the respective value on binary is 1
For this example I would have:
$arr = array(
1 => "a",
4 => "c",
8 => "d",
32 => "f"
);
Or for
$filter=110001
to get
$arr = array(
1 => "a",
2 => "b",
32 => "f"
);
Assuming that the length of $filter is always the same as the number of array elements:
$filter_arr = str_split($filter);
$new_arr = array();
$i = 0;
foreach ($arr as $key => $val) {
if ($filter_arr[$i] == 1) {
$new_arr[$key] = $val;
}
$i++;
}
Using your given array, and filter equal to 101101, $new_arr will equal:
Array
(
[1] => a
[4] => c
[8] => d
[32] => f
)
See demo
This should work for you:
<?php
$arr = array(
1 => "a",
2 => "b",
4 => "c",
8 => "d",
16 => "e",
32 => "f"
);
$filter=110001;
$filerValue = str_split($filter);
$count = 0;
foreach($arr as $k => $v) {
if($filerValue[$count] == 0)
unset($arr[$k]);
$count++;
}
var_dump($arr);
?>
Output:
array(3) {
[1]=>
string(1) "a"
[2]=>
string(1) "b"
[32]=>
string(1) "f"
}
Is there a way to do the following:
$array1 = array( "two" => "2", "three" => "3")
$array2 = array("two", "three", "four")
I want to match array2's value with array1's key. Upon matching, I want to output array1's value.
Thank you
Like Mark Baker commented, you can use array_flip() together with array_intersect_key()
$array1 = array( "two" => "2", "three" => "3");
$array2 = array("two", "three", "four");
$array2 = array_flip($array2);
print_r(array_intersect_key($array1, $array2) );
Output:
Array
(
[two] => 2
[three] => 3
)
$array1 = array( "two" => "2", "three" => "3");
foreach($array1 as $key=>$val){
$array_1[] = $key;
}
$array2 = array("two", "three", "four");
$result = array_diff($array2, $array_1);
print_r($result);
Example:
$arr1 = array('a' => "1", 'b' => "2", 'c' => "3", 'z' => "4");
$arr2 = array('a' => "9", 'b' => "8", 'c' => "7", 'd' => "6", 'e' => "5");
Output:
$result = array(
'a' => array( 'f1' => "1", 'f2' => "9"),
'b' => array( 'f1' => "2", 'f2' => "8"),
'c' => array( 'f1' => "3", 'f2' => "7"),
'd' => array( 'f1' => "0", 'f2' => "6"),
'e' => array( 'f1' => "0", 'f2' => "5"),
'z' => array( 'f1' => "4", 'f2' => "0"),
);
The size of $arr1 can be '>', '<' or '=' size of $arr2
I think this it,
$arr1 = array('a' => "1", 'b' => "2", 'c' => "3", 'z' => "4");
$arr2 = array('a' => "9", 'b' => "8", 'c' => "7", 'd' => "6", 'e' => "5");
foreach($arr1 as $key => $value){
$a[$key]['f1'] = $value;
}
foreach($arr2 as $key => $value){
$b[$key]['f2'] = $value;
}
$c = array_merge_recursive($a, $b);
foreach($c as $key => $value){
$result[$key]['f1'] = (array_key_exists('f1', $value)) ? $value['f1']: 0;
$result[$key]['f2'] = (array_key_exists('f2', $value)) ? $value['f2']: 0;
}
echo "<pre>".print_r ($result, true);
the output:
Array
(
[a] => Array
(
[f1] => 1
[f2] => 9
)
[b] => Array
(
[f1] => 2
[f2] => 8
)
[c] => Array
(
[f1] => 3
[f2] => 7
)
[z] => Array
(
[f1] => 4
[f2] => 0
)
[d] => Array
(
[f1] => 0
[f2] => 6
)
[e] => Array
(
[f1] => 0
[f2] => 5
)
)
array_merge_recursive() should work: http://php.net/manual/en/function.array-merge-recursive.php
otherwise it's simple enough wo implement in a few lines: (Unless you really need the "fn" indices.)
function my_merge(){
$result = array();
foreach(func_get_args() as $a)
foreach($a as $index => $value)
$result[$index][] = $value;
}
Try this:
$keys = array_unique(array_merge(array_keys($arr1), array_keys($arr2)));
$values = array_map(function($key) use ($arr1, $arr2) {
return array('f1' => isset($arr1[$key]) ? $arr1[$key] : "0",
'f2' => isset($arr2[$key]) ? $arr2[$key] : "0"); }
, $keys);
$result = array_combine($keys, $values);
var_dump($result);
Some explanation:
At first get an array $keys of all unique keys of both arrays.
Then for each key the corresponding array of values is then generated.
At last the array of keys and the array of values are combined.
But this does currently only work with two arrays.
Edit Here’s one that works with an arbitrary number of arrays:
$arrays = array($arr1, $arr2);
$keys = array_unique(call_user_func_array('array_merge', array_map('array_keys', $arrays)));
$values = array_map(function($key) use ($arrays) {
return array_combine(array_map(function($key) {
return 'f'.($key+1);
}, array_keys($arrays)),
array_map(function($array) use ($key) {
return isset($array[$key]) ? $array[$key] : "0";
}, $arrays));
}, $keys);
$result = array_combine($keys, $values);
var_dump($result);
Some explanation:
Put all arrays in an array $arrays.
For each array in $arrays, call array_keys on it to get the keys, merge these arrays and get an array $keys of all unique keys.
For each key in $keys, check if the key exists in the array of arrays $arrays.
Combine the keys and values.
$arr1 = array('a' => "1", 'b' => "2", 'c' => "3", 'z' => "4");
$arr2 = array('a' => "9", 'b' => "8", 'c' => "7", 'd' => "6", 'e' => "5");
function combineArray($arr1, $arr2) {
if (is_array($arr1) && is_array($arr2)) {
$rArr = array();
$steps = max ( count($arr1),count($arr2));
$ak1 = array_keys($arr1);
$ak2 = array_keys($arr2);
for ($i=0;$i<$steps;$i++) {
if (!isset($rArr[$i])) $rArr[$i]=array();
$rArr[$i]['f1'] = (isset($arr1[$ak1[$i]])) ? $arr1[$ak1[$i]]: '0';
$rArr[$i]['f2'] = (isset($arr2[$ak2[$i]])) ? $arr2[$ak2[$i]]: '0';
}
return $rArr;
}else {
return false;
}
}
echo "<pre>".print_r (combineArray($arr1, $arr2),true);
might work :)
Run through the first array, store the f1 values from the array and set the default 0 for all f2 values.
Run through the second array, store the f2 values from the array and only set the default 0 for the respective f1 value if it is not already declared.
Use ksort() if desired to alphabetize the first level keys.
Code: (Demo)
$array1 = ['a' => "1", 'b' => "2", 'c' => "3", 'z' => "4"];
$array2 = ['a' => "9", 'b' => "8", 'c' => "7", 'd' => "6", 'e' => "5"];
$result = [];
foreach ($array1 as $k => $v) {
$result[$k] = ['f1' => $v, 'f2' => "0"];
}
foreach ($array2 as $k => $v) {
$result[$k] = ['f1' => $result[$k]['f1'] ?? "0", 'f2' => $v];
}
var_export($result);