Merge and sum two associatve arrays in PHP - php

Given these two arrays:
$first=array(
'books'=>1,
'videos'=>5,
'tapes'=>7,
);
$second=array(
'books'=>3,
'videos'=>2,
'radios'=>4,
'rc cars'=>3,
);
I would like to combine them so that I end up with
$third=array(
'books'=>4,
'videos'=>7,
'tapes'=>7,
'radios'=>4,
'rc cars'=>3,
);
I saw a function here: How to sum values of the array of the same key? but it looses the Key.

You can use something along the lines of:
function sum_associatve($arrays){
$sum = array();
foreach ($arrays as $array) {
foreach ($array as $key => $value) {
if (isset($sum[$key])) {
$sum[$key] += $value;
} else {
$sum[$key] = $value;
}
}
}
return $sum;
}
$third=sum_associatve(array($first,$second));

Just to be different... Uses func_get_args(), closures and enforces arguments to be arrays:
function sum_associative()
{
$data = array();
array_walk($args = func_get_args(), function (array $arg) use (&$data) {
array_walk($arg, function ($value, $key) use (&$data) {
if (isset($data[$key])) {
$data[$key] += $value;
} else {
$data[$key] = $value;
}
});
});
return $data;
}

Related

Check if a value exists multidimensional array and return its key

I have an array, say
$updates = array();
$updates['U1'] = array('F1', 'F2', 'F5');
$updates['U2'] = array('F3');
$updates['U3'] = array('F3', 'F4');
I need search for a value say F5 so it should return the key U1.
And also if there is multiple occurrence of a value, should return the last key.
Eg. searching F3 should return U3 and not U2.
I have searched a lot and can't find a way. I am looking for a solution without using loops.
without using loop:
function findArrVal($arr = [], $param){
static $indx = 0;
if($indx == 0){
krsort($arr);
}
$keys = array_keys($arr);
$values = array_values($arr);
if( count($values) == $indx ){
return false;
} else if( is_array($values[$indx]) && in_array($param, $values[$indx])){
return $keys[$indx];
} else {
++$indx;
return findArrVal($arr, $param);
}
return FALSE;
}
using loop:
function findArrVal($arr = [], $param){
krsort($arr);
foreach($arr as $key => $ar){
if(is_array($ar) && in_array($param, $ar)){
return $key;
}
}
return FALSE;
}
findArrVal($updates,'F3');
krsort - sorts the array in reverse order. ( to find the value at first occurrence )
is_array to check if the child value is an array type.
in_array to find the item on the child array.
Maybe It's helpful for you.
function _getFindArrayKey(array $arr, $key)
{
if (array_key_exists($key, $arr)) {
return true;
}
// check arrays contained in this array
foreach ($arr as $element) {
if (is_array($element)) {
if (_getFindArrayKey($element, $key)) {
return true;
}
}
}
return false;
}

PHP Function Array values not changing

Ive created a function that takes an array as a parameter and changes all values to 4, but it doesn't work and i don't understand why. Really bothering me, could use help thank you!
$cup3 = array (1,4,3,5,7,2);
roll($cup3);
print_r($cup3);
function roll($array)
{
foreach($array as &$value)
{
$value = 4;
}
return $array;
}
Output: (1,4,3,5,7,2) instead of all 4s
Either pass by reference &$array to edit $cup3 directly:
roll($cup3);
print_r($cup3);
function roll(&$array)
{
foreach($array as &$value)
{
$value = 4;
}
}
Or use the return from the function:
$cup3 = roll($cup3);
print_r($cup3);
function roll($array)
{
foreach($array as &$value)
{
$value = 4;
}
return $array;
}

Why "return" on PHP function is not stopping the process?

I do not understand why "return" is not stopping the process in this function that I created to search a value on a multi_level array in PHP.
This is the code:
static function in_array_multi($needle, $haystack) {
foreach ($haystack as $item) {
if(is_array($item)){
in_array_multi($needle, $item);
}
else{
if ($item === $needle) {
return "ok";
}
}
}
return "nok";
}
I am using this array as exemple:
$arr = array(0 => array(id=>1,name=>"cat 1"),
1 => array(id=>2,name=>"cat 2"),
2 => array(id=>3,name=>array(id=>7,name=>"cat 7"))
);
And I am calling the function like this:
echo in_array_multi("cat 1",$arr);
It is returning "nok".
I am using xdebug to follow the process. It should stop the process on the second round.
Someone has any idea about what is happening?
Thanks
My comment was a bit careless. You would only want to return directly from the recursion if the recursion actually finds the value. You could do
function in_array_multi($needle, $haystack) {
foreach ($haystack as $item) {
if(is_array($item)){
if ('ok' === in_array_multi($needle, $item)) {
return 'ok';
}
}
elseif ($item === $needle) {
return "ok";
}
}
return "nok";
}
Because you make the return of function will stop the loop, you should collect it and return in the final.
Maybe you want this..
function array_multiple_search($array, $key, $value=null) {
$return = array();
if (is_array($array)) {
if (isset($array[$key])) {
if (is_null($value)) {
$return[] = $array;
} elseif ($array[$key] == $value) {
$return[] = $array;
}
}
foreach ($array as $subarray) {
$return = array_merge($return, array_multiple_search($subarray, $key, $value));
}
}
return $return;
}
param 1 is the target array
param 2 is the key you want to search of target array
param 3 is the value you want to search with the key of target array(can null)
This function will collect and return an array of qualified.

Unset inside array_walk_recursive not working

array_walk_recursive($arr, function(&$val, $key){
if($val == 'smth'){
unset($val); // <- not working, unset($key) doesn't either
$var = null; // <- setting it to null works
}
});
print_r($arr);
I don't want it to be null, I want the element out of the array completely. Is this even possible with array_walk_recursive?
You can't use array_walk_recursive here but you can write your own function. It's easy:
function array_unset_recursive(&$array, $remove) {
$remove = (array)$remove;
foreach ($array as $key => &$value) {
if (in_array($value, $remove)) {
unset($array[$key]);
} elseif (is_array($value)) {
array_unset_recursive($value, $remove);
}
}
}
And usage:
array_unset_recursive($arr, 'smth');
or remove several values:
array_unset_recursive($arr, ['smth', 51]);
unset($val) will only remove the local $val variable.
There is no (sane) way how you can remove an element from the array inside array_walk_recursive. You probably will have to write a custom recursive function to do so.
The answer of #dfsq is correct but this function doesn't remove empty array. So you can end up with Tree of empty array, which is not what is expected in most cases.
I used this modified function instead:
public function array_unset_recursive(&$array, $remove) {
foreach ($array as $key => &$value) {
if (is_array($value)) {
$arraySize = $this->array_unset_recursive($value, $remove);
if (!$arraySize) {
unset($array[$key]);
}
} else if (in_array($key, $remove, true)){
unset($array[$key]);
}
}
return count($array);
}

access php array children through parameters?

I have a unique case where I have an array like so:
$a = array('a' => array('b' => array('c' => 'woohoo!')));
I want to access values of the array in a manner like this:
some_function($a, array('a')) which would return the array for position a
some_function($a, array('a', 'b', 'c')) which would return the word 'woohoo'
So basically, it drills down in the array using the passed in variables in the second param and checks for the existence of that key in the result. Any ideas on some native php functions that can help do this? I'm assuming it'll need to make use of recursion. Any thoughts would be really appreciated.
Thanks.
This is untested but you shouldn't need recursion to handle this case:
function getValueByKey($array, $key) {
foreach ($key as $val) {
if (!empty($array[$val])) {
$array = $array[$val];
} else return false;
}
return $array;
}
You could try with RecursiveArrayIterator
Here is an example on how to use it.
Here’s a recursive implementation:
function some_function($array, $path) {
if (!count($path)) {
return;
}
$key = array_shift($path);
if (!array_key_exists($key, $array)) {
return;
}
if (count($path) > 1) {
return some_function($array[$key], $path);
} else {
return $array[$key];
}
}
And an iterative implementation:
function some_function($array, $path) {
if (!count($path)) {
return;
}
$tmp = &$array;
foreach ($path as $key) {
if (!array_key_exists($key, $tmp)) {
return;
}
$tmp = &$tmp[$key];
}
return $tmp;
}
These functions will return null if the path is not valid.
$a['a'] returns the array at position a.
$a['a']['b']['c'] returns woohoo.
Won't this do?

Categories