1

I'd like expand on the thread found at Associative array, sum values of the same key.

Table

The OP asks:

Instead of having the key "Conference" repeating 3 times. I want to have it just once and sum the 3 values into one in order.

The answer given is:

 $sum = array_reduce($data, function ($a, $b) {
     isset($a[$b['event']]) ? $a[$b['event']]['budget'] += $b['budget'] : $a[$b['event']] = $b;  
     return $a; });

I have an associative array with more than two values. I'd like to use a function like the one above, but have it sum all key values together, not just 'budget'. Here is an example that reflects my situation:

The array is as follows:

$data = array(
   0 => array(
     'event' => 'Conference',
     'budget' => 3700,
     'people' => 200,
     'rate' => 3000, 
  ),
  1 => array(
    'event' => 'Conference',
    'budget' => 500,
    'people' => 200,
    'rate' => 6000,
  ),
  2 => array(
    'event' => 'Showroom',
    'budget' => 1000,
    'people' => 400,
    'rate' => 30000,
  ),
  3 => array(
    'event' => 'Mission Chez client',
    'budget' => 2000,
    'people' => 200,
    'rate' => 3000,
  ),
  4 => array(
    'event' => 'Séminaire',
    'budget' => 700,
    'people' => 40,
    'rate' => 3000,
  ),
  5 => array(
    'event' => 'Livraison',
    'budget' => 4000,
    'people' => 2,
    'rate' => 3000,
  ),
  6 => array(
    'event' => 'Conference',
    'budget' => 334,
    'people' => 200,
    'rate' => 9000,
  ),
);

If I use the code above, I will be able to reduce 'Conference' to one entry, as follows:

[0] => Array
        (
            [event] => Conference
            [budget] => 4534
            [people] => 200
            [rate] => 5000
        )

The budget figure is correct. But the people figure isn't. How could I get the sum of 'people' as well as 'budget', so that [people] => 600?

Finally, is it possible to easily get an average value for 'rate'? So, for conference it would be ((3000+6000+9000) / 3 = 6000).

All in all, I'm seeking to organize the table to get a result like:

[0] => Array
            (
                [event] => Conference  // Key that appears multiple times
                [budget] => 4534  //Sum of all conference budget
                [people] => 600  //Sum of all conference people
                [rate] => 5000  //Average rate of conference
            )
Community
  • 1
  • 1
Chris
  • 191
  • 16
  • Are you opposed to bringing in a 3rd party library here? Laravel's collections has some methods that would help out with this. – FatBoyXPC Mar 05 '17 at 22:54
  • Fair question. If it has to go the way of 3rd party libraries, then so be it. :) But this is for a fairly modest online dashboard project, to be used by only a few partners. So I'd like to only buy shared hosting if possible, to save $$. As I understand it, shared hosting can be limited in terms of what you can install. Hmm... you've got me wondering. – Chris Mar 05 '17 at 22:56
  • @FatBoyXPC why do you want to bring a huge cannon for a simple loop? Any 3rd party library in this case won't make it faster unless it is a php extension in C. It only may make it more easily readable but surely not more efficient. – Zefiryn Mar 05 '17 at 23:03
  • I wouldn't consider this a "huge cannon". That's also why I asked, rather than out right suggesting. – FatBoyXPC Mar 05 '17 at 23:06

1 Answers1

2

Try

 $sum = array_reduce($data, function ($a, $b) {
     if (!isset($a[$b['event']])) {
          $a[$b['event']] = $b;
     } else {
         $a[$b['event']]['budget'] += $b['budget'];
         $a[$b['event']]['people'] += $b['people'];
         $a[$b['event']]['rate'] += $b['rate'];
     }
 return $a; });

For averages you could try:

 $sum = array_reduce($data, function ($a, $b) {
     if (!isset($a[$b['event']])) {
          $a[$b['event']] = $b;
          $a[$b['event']]['rate_count'] = 1;
          $a[$b['event']]['average_rate'] = array($b['rate']);
     } else {
         $a[$b['event']]['budget'] += $b['budget'];
         $a[$b['event']]['people'] += $b['people'];
         $a[$b['event']]['rate'] += $b['rate'];
         $a[$b['event']]['rate_count'] += 1;
         $a[$b['event']]['average_rate'] = $a[$b['event']]['rate'] / $a[$b['event']]['rate_count'];
     }
 return $a; });
Zefiryn
  • 2,240
  • 2
  • 20
  • 30