1

What is the best way to sum the 'val' field with the same 'color' for each different color:

Array
(
    [0] => Array
        (
            [color]=> "red"
            [val]=> 4
        )

    [1] => Array
        (
            [color]=> "green"
            [val]=> 3
        )

    [2] => Array
        (
            [color]=> "blue"
            [val]=> 1
        )

    [3] => Array
        (
            [color]=> "green"
            [val]=> 6
        )

    [4] => Array
        (
            [color]=> "blue"
            [val]=> 2
        )
)

Desired result : red: 4; green: 9; blue: 3.

Regards, Elio Fernandes

1
  • 2
    I'm sure there is a super slick way to do this in one line using array_walk or callbacks, but there is something to be said about the readability of a simple loop. I would loop it. Also, 'best' is subjective. As far as performance is concerned, both methods are probably about the same. Commented Nov 7, 2017 at 14:58

6 Answers 6

4

I would do it this way, with a foreach loop:

$temp = [];
foreach($arr as $value) {
    //check if color exists in the temp array
    if(!array_key_exists($value['color'], $temp)) {
        //if it does not exist, create it with a value of 0
        $temp[$value['color']] = 0;
    }
    //Add up the values from each color
    $temp[$value['color']] += $value['val'];
}
Sign up to request clarification or add additional context in comments.

Comments

2

You can use array_reduce to have less and more readable code:

$array = array
(
    0 => array("color"=> "red","val"=> 4),
    1 => array("color"=> "blue","val"=> 3),
    2 => array("color"=> "blue","val"=> 1)
);

function sum($accumulator, $item){
    $accumulator[$item['color']] = $accumulator[$item['color']] ?? 0;
    $accumulator[$item['color']] += $item['val'];
    return $accumulator;
}

$sum = array_reduce($array, "sum");
var_dump($sum); // return here array(2) { ["red"]=> int(4) ["blue"]=> int(4) }

And the documentation: http://php.net/manual/en/function.array-reduce.php

1 Comment

This doesn't take the colours into account
1

I would loop it for readability's sake.

$output = array();
foreach($array as $value){
    if(!isset($output[$value['color']])) $output[$value['color']] = 0; //Ensure the value is 0 if it doesn't exist
    $output[$value['color']] += $value['val']; //Add the total for that color
}

This will return an array of colors to total counts.

1 Comment

I like the simple elegance of just keeping it old school. Clean, direct, to the point.
1

Personally I'd do something like this with array_reduce, but as mentioned above it might not be the most readable option. Definitely a matter of opinion though.

$result = array_reduce($array, function ($carry, $item) {
    $carry[$item['color']] = $carry[$item['color']] ?? 0;
    $carry[$item['color']] += $item['val'];
    return $carry;
}, []);

See https://eval.in/894644

Edit: Fix notices

2 Comments

Is array_reduce faster than a loop? I like this solution either way, but I'm curious :)
Can't imagine there's much in it, but if I had to guess I'd say a loop was probably faster. Although obviously unless you're talking about an array with 100,000 items in it, you won't notice.
0

To keep up the speed, without the foreach loop, I would say to do it like this:

    $array = [
                [
                    "color" => "red",
                    "val" => "4"
                ],
                [
                    "color" => "green",
                    "val" => "3"
                ],
                [
                    "color" => "blue",
                    "val" => "1"
                ],
                [
                    "color" => "green",
                    "val" => "6"
                ],
                [
                    "color" => "blue",
                    "val" => "2"
                ]
       ];

    $array = array_values(array_reduce(
         $array,

           function (array $a, array $v) {
              $k = "".$v['color']."";
                    
              if (!array_key_exists($k, $a)) {
                  $a[$k] = $v;   
              } else {
                  $a[$k]['val'] += $v['val'];
              }
              return $a;              
          },
       array()                   
    ));

var_dump($array);

Comments

-1
$arrays = array( 
         array(
                "color"=>"red",
                "val"=>4
         ),
         array( 
               "color"=>"green",
               "val"=>3
        )
);
foreach ($color as $array) {
    echo $array["color"].": ".$array["val"].";";
}

1 Comment

This will spew notices all over.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.