views:

546

answers:

3

Hod do I multiply the values of a multi-dimensional array with weigths and sum up the results into a new array in PHP or in general?

The boring way looks like this:

$weights = array(0.25, 0.4, 0.2, 0.15);
$values  = array
           ( 
             array(5,10,15), 
             array(20,25,30), 
             array(35,40,45), 
             array(50,55,60)
           );
$result  = array();

for($i = 0; $i < count($values[0]); ++$i) {
  $result[$i] = 0;
  foreach($weights as $index => $thisWeight)
    $result[$i] += $thisWeight * $values[$index][$i];
}

Is there a more elegant solution?

A: 

Hm...

foreach($values as $index => $ary )
  $result[$index] = array_sum($ary) * $weights[$index];
Tomalak
I think you missunderstood my question: I want to end up with an array of weighted sums, not the sum of all sums. Which means that $result is of dimension 1xcount($values[0]).
christian studer
A: 

I had also misunderstood the question at first.

I guess that with that data representation any other choice would be less clear than what you have.

If we could change it to something else, for instance if we were to transpose the matrix and multiply the other way around, then it would be very easy to get a more succint and probably elegant way.

<?php

$weights = array(0.2,0.3,0.4,0.5);
$values = array(array(1,2,0.5), array(1,1,1), array(1,1,1), array(1,1,1));
$result = array();

for($i = 0; $i < count($values[0]); ++$i) {
        $result[$i] = 0;
        foreach($weights as $index => $thisWeight) {
           $result[$i] += $thisWeight * $values[$index][$i];
        }
}
print_r($result);


$result = call_user_func_array("array_map",array_merge(array("weightedSum"),$values));

function weightedSum() {
    global $weights;
    $args = func_get_args();
    return array_sum(array_map("weight",$weights,$args));
}

function weight($w,$a) {
    return $w*$a;
}

print_r($result);

?>
Vinko Vrsalovic
+1  A: 

Depends on what you mean by elegant, of course.

function weigh(&$vals, $key, $weights) {
    $sum = 0;
    foreach($vals as $v)
        $sum += $v*$weights[$key];
    $vals = $sum;
}

$result = $values;
array_walk($result, "weigh", $weights);

EDIT: Sorry for not reading your example better. I make result a copy of values, since array_walk works by reference.

gnud
This is not what he's asking for.
Vinko Vrsalovic
It is if you remove the last array_sum. I'll do that now.
gnud
You're right. Sorry. Here it is :/
gnud