How to merge two arrays by summing the merged values [duplicate] - php

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
PHP: How to sum values of the array of the same key
I am looking for an array_merge() function that does NOT replace values, but ADDS them.
Example, this is the code I am trying:
echo "<pre>";
$a1 = array(
"a" => 2
,"b" => 0
,"c" => 5
);
$a2 = array(
"a" => 3
,"b" => 9
,"c" => 7
,"d" => 10
);
$a3 = array_merge($a1, $a2);
print_r($a3);
Sadly, this outputs this:
Array
(
[a] => 3
[b] => 9
[c] => 7
[d] => 10
)
I then tried, instead of array_merge, just simply adding the two arrays
$a3 = $a1 + $a2;
But this outputs
Array
(
[a] => 2
[b] => 0
[c] => 5
[d] => 10
)
What I truly want is to be able to pass as many arrays as needed, and then get their sum. So in my example, I want the output to be:
Array
(
[a] => 5
[b] => 9
[c] => 12
[d] => 10
)
Of course I can schlepp and build some function with many foreach etc, but am looking or a smarter, cleaner solution. Thanks for any pointers!

$sums = array();
foreach (array_keys($a1 + $a2) as $key) {
$sums[$key] = (isset($a1[$key]) ? $a1[$key] : 0) + (isset($a2[$key]) ? $a2[$key] : 0);
}
You could shorten this to the following using the error suppression operator, but it should be considered ugly:
$sums = array();
foreach (array_keys($a1 + $a2) as $key) {
$sums[$key] = #($a1[$key] + $a2[$key]);
}
Alternatively, some mapping:
$keys = array_fill_keys(array_keys($a1 + $a2), 0);
$sums = array_map(function ($a1, $a2) { return $a1 + $a2; }, array_merge($keys, $a1), array_merge($keys, $a2));
Or sort of a combination of both solutions:
$sums = array_fill_keys(array_keys($a1 + $a2), 0);
array_walk($sums, function (&$value, $key, $arrs) { $value = #($arrs[0][$key] + $arrs[1][$key]); }, array($a1, $a2));
I think these are concise enough to adapt one of them on the spot whenever needed, but to put it in terms of a function that accepts an unlimited number of arrays and sums them:
function array_sum_identical_keys() {
$arrays = func_get_args();
$keys = array_keys(array_reduce($arrays, function ($keys, $arr) { return $keys + $arr; }, array()));
$sums = array();
foreach ($keys as $key) {
$sums[$key] = array_reduce($arrays, function ($sum, $arr) use ($key) { return $sum + #$arr[$key]; });
}
return $sums;
}

My contribution:
function array_merge_numeric_values()
{
$arrays = func_get_args();
$merged = array();
foreach ($arrays as $array)
{
foreach ($array as $key => $value)
{
if ( ! is_numeric($value))
{
continue;
}
if ( ! isset($merged[$key]))
{
$merged[$key] = $value;
}
else
{
$merged[$key] += $value;
}
}
}
return $merged;
}
Pass as many arrays to it as you want. Feel free to add some more defense, ability to accept multidimensional arrays, or type checking.
Demo: http://codepad.org/JG6zwAap

its not so complicate
do something like:
$a3 = $a1;
foreach($a2 as $k => $v) {
if(array_key_exists($k, $a3)) {
$a3[$k] += $v;
} else {
$a3[$k] = $v;
}
}

Related

Php convert multidimensional array to single array [duplicate]

This question already has answers here:
How to Flatten a Multidimensional Array?
(31 answers)
Closed 3 years ago.
How can I convert multidimensional array into single array
Input
[["4|1","4|3","4|6"],[["4|1|2","4|1|8"],["4|3|4","4|3|9"],["4|6|5","4|6|12"]]]
How can I convert above input as below ?
["4|1","4|3","4|6","4|1|2","4|1|8","4|3|4","4|3|9","4|6|5","4|6|12"]
I see you want to flatten an array to 1-D. Here is recursive iterator class you can use,
$arr = [["4|1","4|3","4|6"],[["4|1|2","4|1|8"],["4|3|4","4|3|9"],["4|6|5","4|6|12"]]];
$iterator = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($arr));
$result = [];
foreach($iterator as $v) {
$result[] = $v;
}
print_r($result);
RecursiveArrayIterator - This iterator allows to unset and modify values and keys while iterating over Arrays and Objects in the same way as the ArrayIterator. Additionally, it is possible to iterate over the current iterator entry.
Ref.
Demo
Solution 2:-
$arr = [["4|1","4|3","4|6"],[["4|1|2","4|1|8"],["4|3|4","4|3|9"],["4|6|5","4|6|12"]]];
array_walk_recursive($arr, function($v) use(&$result){
$result[] = $v;
});
print_r($result);
Demo
Output:-
Array
(
[0] => 4|1
[1] => 4|3
[2] => 4|6
[3] => 4|1|2
[4] => 4|1|8
[5] => 4|3|4
[6] => 4|3|9
[7] => 4|6|5
[8] => 4|6|12
)
You can use array_merge().
$arrays = [["4|1","4|3","4|6"],[["4|1|2","4|1|8"],["4|3|4","4|3|9"],["4|6|5","4|6|12"]]]
$arrayMerge = []
foreach($arrays as $array)
{
$arrayMerge = array_merge($arrayMerge, $array)
}
For more info: https://www.php.net/manual/es/function.array-merge.php
Try this solution. I have used a couple of foreach loops to make it simple.
<?php
$array = [["4|1","4|3","4|6"],[["4|1|2","4|1|8"],["4|3|4","4|3|9"],["4|6|5","4|6|12"]]];
foreach ($array as $key => $value) {
if($key == 0)
{
foreach ($value as $key => $v) {
$new_array[] = $v;
}
}
else
{
foreach ($value as $key => $s_value) {
foreach ($s_value as $key => $s) {
$new_array[] = $s;
}
}
}
}
print_r($new_array);
?>
Here is the live demo for you.
Use array_walk_recursive, check Demo
$result = [];
$multidimension_array = [["4|1","4|3","4|6"],[["4|1|2","4|1|8"],["4|3|4","4|3|9"],["4|6|5","4|6|12"]]];
array_walk_recursive($multidimension_array, function($v) use (&$result) { $result[] = $v; });
print_r($result);

Any other better logic for this programme

Today in an interview i got the following question to solve without using any inbuilt function eg in_array and etc.I am able to solve the programme but they told me is there any better approach and also they told me the total code is only upto 7 lines.So can anyone tell me any better approach than this:-
<?php
$a = array(1,3,5,2,1,5,11,16);
$b = array(1,4,3,11,12,5,7,18);
$final = [];
for($i=0;$i<count($a);$i++){
$flag = 0;
if($i==0){
$final[] = $a[$i];
} else {
for($j=0;$j<count($final);$j++){
if($a[$i] == $final[$j]){
$flag = 1;
}
}
if($flag==0){
$final[] = $a[$i];
}
for($k=0;$k<count($final);$k++){
if($b[$i] == $final[$k]){
$flag = 1;
}
}
if($flag==0){
$final[] = $b[$i];
}
}
}
echo '<pre>';
print_r($final);
the result would be the final array which would contain unique array of both eg
Array ( [0] => 1 [1] => 3 [2] => 4 [3] => 5 [4] => 2 [5] => 11 [6] => 16 [7] => 18 )
Here is how you could do it without using built-in functions: Collect the values as keys (so they are unique), and then put those keys back as values in the final array:
$a = array(1,3,5,2,1,5,11,16);
$b = array(1,4,3,11,12,5,7,18);
foreach($a as $v) $keys[$v] = 1;
foreach($b as $v) $keys[$v] = 1;
foreach($keys as $k => $v) $final[] = $k;
echo '<pre>';
print_r($final);
See it run on eval.in.
Just set the key as the value and they will overwrite. If the arrays are the same length:
foreach($a as $k => $v) {
$final[$v] = $v;
$final[$b[$k]] = $b[$k];
}
If not, then do it for each array:
foreach(array($a, $b) as $c) {
foreach($c as $v) {
$final[$v] = $v;
}
}
The order and keys won't be the same, but that wasn't stated as a requirement.

PHP - Use multiple values in foreach loop

I have the two PHP loops as below:
foreach ($directData as $key => $val) {
echo $val;
echo "|"; //Just for the visual.
}
foreach ($sdata as $key => $val) {
echo $val;
echo "|"; //Just for the visual.
}
Which output:
5|5|5|10|10|10|0| and the second: 2|2|2|5|5|5|20|
My question is, how can I combine these two result (add them) and print it out like above?
So, it would be:
7|7|7|15|15|15|20
php > $a = [1, 2, 3];
php > $b = [4, 5, 6];
php > $c = array_map(function($x, $y){ return $x + $y; }, $a, $b);
php > print_r($c);
Array
(
[0] => 5
[1] => 7
[2] => 9
)
php > print_r(implode($c, '|') . '|');
5|7|9|
Broken down for better readability, this will sum them into $new array.
array_map will iterate through both given arrays and apply the callback function to both of the arrays at their current indexes. The callback function will sum the values of at current indexes.
$new=array_map(
function(){
return array_sum(func_get_args());
},
$directData, $sdata
);
$out= '';
foreach ($new as $key => $val)
$out .= $val.'|';
echo rtrim($out,'|');
in simple way you can do it like:
$finalData = array_map(function () {
return array_sum(func_get_args());
}, $directData, $sdata );
print_r($finalData );
If each index corresponds in the arrays
$rezult = array();
for($i=0;$i<count($directData);$i++){
$rezult[] = $directData[$i] + $sdata[$i];
}
echo join("|",$rezult);
Here is a method that uses the iterators that all PHP arrays have.
/**
* Use the iterator that all PHP arrays have.
*
* Check both arrays for having entries.
*/
$listOut = array(); // output in here
while (current($listA) !== false && current($listB) !== false) {
$listOut[] = current($listA) + current($listB);
next($listA);
next($listB);
}
Input:
$listA = array(5, 5, 5, 10, 10, 10, 0);
$listB = array(2, 2, 2, 5, 5, 5, 20, );
Output
Array
(
[0] => 7
[1] => 7
[2] => 7
[3] => 15
[4] => 15
[5] => 15
[6] => 20
)
7| 7| 7| 15| 15| 15| 20

Trouble finding odd results of an array

I can't seem to find the answer to these problem. I have the following php code.
$r = 1,2,3,4,5,6 and so on
and i want to get the number like this
$result = 1,3,5
or if i have
$s = b,c,d,e,f,g,h,i...and so on
the result should be
$results c,e,g,i
Pretty easy with numbers, the trick with letters is to use ord()
$arr = array(1,2,3,4,5,6);
$arr = array_filter ($arr, function ($number) {
return $number % 2;
});
print_r($arr);
$arr = array('a', 'b', 'c', 'd', 'e');
$arr = array_filter ($arr, function ($letter) {
return ord($letter) % 2;
});
print_r($arr);
Output :
Array (
[0] => 1
[2] => 3
[4] => 5
)
Array (
[0] => a
[2] => c
[4] => e
)
And here is a generic solution, working with both letters and numbers :
$arr = array_filter ($arr, function ($value) {
$value = is_int($value) ? $value : ord($value);
return $value % 2;
});
This will work:
$a = array(1,2,3,4,5,6);
foreach($a as $k => $v){
if($k&1){
unset($a[$k]);
}
}
print_r($a);

PHP: Turning multidimensional arrays to single dimension arrays

Basically my app is interacting with a web service that sends back a weird multidimensional array such as:
Array
(
[0] => Array
(
[Price] => 1
)
[1] => Array
(
[Size] => 7
)
[2] => Array
(
[Type] => 2
)
)
That's not a problem, but the problem is that the service keeps changing the index of those items, so in the next array the Price could be at 1 instead of 0.
How do I effeciently transform arrays like this into a single dimension array so I can access the variables through $var['Size'] instead of $var[1]['Size']?
Appreciate your help
$result = call_user_func_array('array_merge', $array);
Like this:
$result = array();
foreach($array as $inner) {
$result[key($inner)] = current($inner);
}
The $result array would now look like this:
Array
(
[Price] => 1
[Size] => 7
[Type] => 2
)
I am using laravel's helper: http://laravel.com/api/source-function-array_flatten.html#179-192
function array_flatten($array)
{
$return = array();
array_walk_recursive($array, function($x) use (&$return) { $return[] = $x; });
return $return;
}
function flattenArray($input, $maxdepth = NULL, $depth = 0)
{
if(!is_array($input)){
return $input;
}
$depth++;
$array = array();
foreach($input as $key=>$value){
if(($depth <= $maxdepth or is_null($maxdepth)) && is_array($value)){
$array = array_merge($array, flattenArray($value, $maxdepth, $depth));
} else {
array_push($array, $value);
// or $array[$key] = $value;
}
}
return $array;
}
Consider $mArray as multidimensional array and $sArray as single dimensional array this code will ignore the parent array
function flatten_array($mArray) {
$sArray = array();
foreach ($mArray as $row) {
if ( !(is_array($row)) ) {
if($sArray[] = $row){
}
} else {
$sArray = array_merge($sArray,flatten_array($row));
}
}
return $sArray;
}
I think i found best solution to this : array_walk_recursive($yourOLDmultidimarray, function ($item, $key) {
//echo "$key holds $item\n";
$yourNEWarray[]=$item;
});
If you use php >= 5.6, you may use array unpacking (it's much faster):
$result = array_merge(...$array);
See wiki.php.net on unpacking

Categories