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 th
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%.
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.
foreach ($arr2 as $key => $value) {
if(array_key_exists($key, $arr1) && array_key_exists($key, $arr2))
$ret[$key] = $arr2[$key] - $arr1[$key];
}
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