12

So I have this associative array (dump done with kint)

dump done with Kint d

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 to have something like:

Conference : 4534

And same thing for all other keys that are repeating..

Is there a native function that can do that ?

KingCrunch
  • 128,817
  • 21
  • 151
  • 173
Alucard
  • 1,814
  • 1
  • 21
  • 33

5 Answers5

34

You can try

$data = array(
  0 => array(
    'event' => 'Conference',
    'budget' => 3700,
  ),
  1 => array(
    'event' => 'Conference',
    'budget' => 500,
  ),
  2 => array(
    'event' => 'Showroom',
    'budget' => 1000,
  ),
  3 => array(
    'event' => 'Mission Chez client',
    'budget' => 2000,
  ),
  4 => array(
    'event' => 'Séminaire',
    'budget' => 700,
  ),
  5 => array(
    'event' => 'Livraison',
    'budget' => 4000,
  ),
  6 => array(
    'event' => 'Conference',
    'budget' => 334,
  ),
);

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


print_r(array_values($sum));

Output

Array
(
    [0] => Array
        (
            [event] => Conference
            [budget] => 4534
        )

    [1] => Array
        (
            [event] => Showroom
            [budget] => 1000
        )

    [2] => Array
        (
            [event] => Mission Chez client
            [budget] => 2000
        )

    [3] => Array
        (
            [event] => Séminaire
            [budget] => 700
        )

    [4] => Array
        (
            [event] => Livraison
            [budget] => 4000
        )

)
Baba
  • 94,024
  • 28
  • 166
  • 217
  • It preserves the second key "budget" but not the first one "event", it gives this: [link](http://d.pr/i/7rKM) – Alucard Jan 07 '13 at 13:00
  • I really need to keep the same structure but sum values with the same key – Alucard Jan 07 '13 at 13:01
  • Thx Baba, it is exactly what I'm looking for, but it seems that the values are sumed twice: 1- original array [link](http://d.pr/i/AfGz) 2- array after sum function [link](http://d.pr/i/8tEP) 'Livraison' for example should have 4000, any idea why It has 8000 ? – Alucard Jan 07 '13 at 13:27
  • I can't work with image ... use print_r of the original array and add it to pastebin – Baba Jan 07 '13 at 13:31
  • Original array [link](http://pastebin.com/C2KenBt5) . Results array [link](http://pastebin.com/KpeSNrjx) – Alucard Jan 07 '13 at 13:39
5

A simple suggestion:

$results = array();
foreach ($budgetByEventTemp as $value)
{
  if( ! isset($results[$value['event']]) )
  {
     $results[$value['event']] = 0;
  }

  $results[$value['event']] += $value['budget'];

}

var_dump($results);

Update according to comments

You can run over them again:

foreach($results as $key => $value)
{
  $structured_results[] = array('event' => $key, 'budget' => $value);
}

var_dump($structured_results);
Repox
  • 15,015
  • 8
  • 54
  • 79
  • Thank you for the suggestion, but that would not preserve the keys of the array (event and budget) – Alucard Jan 07 '13 at 12:42
  • I fail to see why it should, when you wan't to sum up the values? – Repox Jan 07 '13 at 13:05
  • This array is encoded via json and sent to be cooked somewhere else, so I need to preserve the same structure and just sum values with the same key – Alucard Jan 07 '13 at 13:09
1
$sumArray = array();

foreach ($myArray as $k=>$subArray) {
foreach ($subArray as $id=>$value) {
  $sumArray[$id]+=$value;
  }
}

print_r($sumArray);
웃웃웃웃웃
  • 11,829
  • 15
  • 59
  • 91
0

This option will group and sum values of all repeated indexes in an array.

Code here :

$aValues[]=array("nametogroup",10);
$aValues[]=array("nametogroup",20);
$aValues[]=array("nametogroup2",30);
$aValues[]=array("nametogroup2",20);
echo var_dump($aValues); // array before grouping
foreach ($aValues as  $id=>$value) 
{
  $a2sum["{$value[0]}"]=$value[1] + $a2sum["{$value[0]}"];
}
echo var_dump($a2sum); //array after group and adding values

This will result into:

array
0 => 
array
  0 => string nametogroup (length=11)
  1 => int 10
1 => 
array
  0 => string nametogroup (length=11)
  1 => int 20
2 => 
array
  0 => string nametogroup2 (length=12)
  1 => int 30
3 => 
array
  0 => string nametogroup2 (length=12)
  1 => int 20

array
nametogroup => int 30
nametogroup2 => int 50
I'm Geeker
  • 4,601
  • 5
  • 22
  • 41
Sultanos
  • 463
  • 7
  • 12
0

To iterate a set of data and return a potentially smaller set of data, array_reduce() is a wise "functional" choice. Here is a slight variation on @Baba's answer using a null coalescing operator and a more intuitive variable naming convention.

Code: (Demo)

var_export(
    array_reduce(
        $data,
        function ($carry, $row) {
            $carry[$row['event']] = ($carry[$row['event']] ?? 0) + $row['budget'];
            return $carry;
        }
    )
);
mickmackusa
  • 43,625
  • 12
  • 83
  • 136