Home » Php » PHP subtract array values

PHP subtract array values

Posted by: admin July 12, 2020 Leave a comment

Questions:

I have an array with keys and values. Each value is an integer. I have an other array with the same keys. How can I subtract all of the values for the matching keys? Also there might be keys that do not occur in the second array but both arrays have the same length. If there is a key in array 2 that is not present in array 1 its value should be unchanged. If there is a key in the first array that is not in the second it should be thrown away. How do I do it? Is there any built-in function for this?

If I would write a script it would be some kind of for loop like this:

$arr1 = array('a' => 1, 'b' => 3, 'c' => 10);
$arr2 = array('a' => 2, 'b' => 1, 'c' => 5);
$ret = array();
foreach ($arr1 as $key => $value) {
    $ret[$key] = $arr2[$key] - $arr1[$key];
}
print_r($ret);
/*
should be: array('a' => 1, 'b' => -2, 'c' => -5)
*/

I did not add the occasion here a key is in one array and not in the other.

How to&Answers:

You could avoid the foreach using array functions if you were so inclined.

The closure provided to array_mapdocs below will subtract each $arr1 value from each corresponding $arr2. Unfortunately array_map won’t preserve your keys when using more than one input array, so we use array_combinedocs to merge the subtracted results back into an array with the original keys:

$arr1 = array('a' => 1, 'b' => 3, 'c' => 10);
$arr2 = array('a' => 2, 'b' => 1, 'c' => 5);

$subtracted = array_map(function ($x, $y) { return $y-$x; } , $arr1, $arr2);
$result     = array_combine(array_keys($arr1), $subtracted);

var_dump($result);

UPDATE

I was interested in how the array functions approach compared to a simple foreach, so I benchmarked both using Xdebug. Here’s the test code:

$arr1 = array('a' => 1, 'b' => 3, 'c' => 10);
$arr2 = array('a' => 2, 'b' => 1, 'c' => 5);

function arrayFunc($arr1, $arr2) {
  $subtracted = array_map(function ($x, $y) { return $y-$x; } , $arr1, $arr2);
  $result     = array_combine(array_keys($arr1), $subtracted);
}

function foreachFunc($arr1, $arr2) {
  $ret = array();
  foreach ($arr1 as $key => $value) {
    $ret[$key] = $arr2[$key] - $arr1[$key];
  }
}

for ($i=0;$i<10000;$i++) { arrayFunc($arr1, $arr2); }
for ($i=0;$i<10000;$i++) { foreachFunc($arr1, $arr2); }

As it turns out, using the foreach loop is an order of magnitude faster than accomplishing the same task using array functions. As you can see from the below KCachegrind callee image, the array function method required nearly 80% of the processing time in the above code, while the foreach function required less than 5%.

enter image description here

The lesson here: sometimes the more semantic array functions (surprisingly?) can be inferior performance-wise to a good old fashioned loop in PHP. Of course, you should always choose the option that is more readable/semantic; micro-optimizations like this aren’t justified if they make the code more difficult to understand six months down the road.

Answer:

foreach ($arr2 as $key => $value) {
    if(array_key_exists($key, $arr1) && array_key_exists($key, $arr2))
        $ret[$key] = $arr2[$key] - $arr1[$key];
}

Answer:

PHP does not offer vectorized mathematical operations. I would stick with your current approach of using a loop.

First, I would get the set of array keys for each array. (See the array_keys function). Then, intersect them. Now you will have the keys common to each array. (Take a look at the array_intersect function). Finally, iterate. It’s a readable and simple approach.

Lastly, you could take a look at a library, such as Math_Vector: http://pear.php.net/package/Math_Vector