0

There are many nice Q&A on Stackoverflow on how to take a multidimensional associative array and sum values in it. Unfortunately, I can't find one where the key names aren't lost.

For example:

$arr=array(
      array('id'=>'1', 'amount'=>'5'),
      array('id'=>'1', 'amount'=>'5'),
      array('id'=>'2', 'amount'=>'1'),
      array('id'=>'2', 'amount'=>'3')
);

I want the resulting array to look like this:

$result=array(
  array('id'=>'1', 'amount'=>'10'),
  array('id'=>'2', 'amount'=>'4')
);

Unfortunately the only thing I can figure out how to do is this:

$result = array();
foreach($arr as $amount){
  if(!array_key_exists($amount['id'], $arr))          
  $result[$amount['id']] =0; 
  $result[$amount['id']] += $amount['amount'];
}

Which when echo'd as follows produces (notice the lack of the keys' words "id" and "amount"):

foreach($result as $id => $amount){
  echo $id."==>".$amount."\n";
}

1==>10
2==>4
Community
  • 1
  • 1
tim peterson
  • 23,653
  • 59
  • 177
  • 299
  • The key names exist, you are just aren't outputting them. At least, they should if you ran the code you showed. – crush Feb 05 '13 at 20:00
  • @crush thanks, so I don't need what Colin suggests below? I'm a little confused still, can you fiddle a bit? ==> http://writecodeonline.com/php/ – tim peterson Feb 05 '13 at 20:03
  • @timpeterson The keys are not there in your resulting array. Not sure what crush is referring to. May I ask what you need the array in this structure for anyway? – Colin M Feb 05 '13 at 20:07
  • The keys are there. They just aren't in the dimension you are iterating through. – crush Feb 05 '13 at 20:09
  • @ColinMorelli, i need to ultimately produce a json object so `$results` needs to be an associative array so I can `json_encode` it. Is there something specific you're trying to tell me? – tim peterson Feb 05 '13 at 20:10
  • @crush can you provide code? – tim peterson Feb 05 '13 at 20:10
  • @crush You're talking about a technicality given the fact that the OP is using the `$arr` array for the source data and resulting data - which I doubt would really be the case. Using the summing method the OP is describing would not yield the array keys in the result. It would only give the ID as the array key, and the sum as its value. Tim, I'd advise you just use my suggestion. – Colin M Feb 05 '13 at 20:12
  • @ColinMorelli yeah that was a mistake (now corrected), thanks, i'll use your answer... – tim peterson Feb 05 '13 at 20:14
  • @timpeterson Looks like you changed the code you originally posted. Cool. – crush Feb 05 '13 at 20:17

2 Answers2

1

This is just to show that you already had the data you originally needed, though, the answer you accepted is a better way to deal with it.

You have the following to start with right?

$arr = array(
    array('id'=>'1', 'amount'=>'5'),
    array('id'=>'1', 'amount'=>'5'),
    array('id'=>'2', 'amount'=>'1'),
    array('id'=>'2', 'amount'=>'3')
);

Output

Array
(
    [0] => Array
        (
            [id] => 1
            [amount] => 5
        )
    [1] => Array
        (
            [id] => 1
            [amount] => 5
        )
    [2] => Array
        (
            [id] => 2
            [amount] => 1
        )
    [3] => Array
        (
            [id] => 2
            [amount] => 3
        )
)

Then you run it through the following algorithm:

$summedArr = array();

foreach ($arr as $amount) {
    $summedArr['amount'][$amount['id']] += $amount['amount'];
    $summedArr['id'][$amount['id']] = $amount['id'];
}

Now, disregarding the Notice warnings that are produced since you are referencing indexes that don't yet exist, this outputs the following:

Output

Array
(
    [amount] => Array
        (
            [1] => 10
            [2] => 4
        )
    [id] => Array
        (
            [1] => 1
            [2] => 2
        )
)

Do you see the keys, yet? Because I do.

Now iterate over the array:

foreach ($summedArr as $key => $value) {
    echo $k . "==>" . $v . "\n";
}

Output

amount==>Array
id==>Array

That's not what you want, though. You want:

foreach ($summedArr as $key => $arr) {
    foreach ($arr as $v) {
        echo $key . "==>" . $v;
    }
}
crush
  • 16,713
  • 9
  • 59
  • 100
  • The OP removed that code and changed it out for a different counting algorithm. And either way, despite the keys being there, they're still not in the format the OP needs them in. You'll see he was using them for `json_encode`ing the results back to a browser - so either way the arrays will have to be reconstructed per my suggestion – Colin M Feb 05 '13 at 20:16
  • Sure they are. He simply wasn't referencing them right. I just now saw the that he switching the code out later. I was obviously referencing the original code. You can stop with your snarky comments. I'm not trying to steal your accepted answer kid. Notice how I endorse it at the beginning of mine. – crush Feb 05 '13 at 20:18
  • Not about the accepted answer, it's about getting the right solution. Go ahead and `json_encode` your result so that the OP can access them in javascript like this: `results[0].id` and `results[0].amount` without reconstructing arrays. Apologize if I came off rude - wasn't the intention. I just don't believe this is what the OP needs – Colin M Feb 05 '13 at 20:20
  • Who said anything about not reconstructing arrays? The OP was echoing plain strings originally, not encoding JSON. Get over yourself. Yes, he would have to reconstruct the array. That is obvious. – crush Feb 05 '13 at 20:20
  • @crush sorry about this. I didn't see my mistakes. Colin's answer works for me but I upvoted your answer b/c I appreciate your effort. I just need some more minutes to make sense of it... – tim peterson Feb 05 '13 at 20:21
  • @crush My intention isn't to be rude - but the OP stated he needs to `json_encode` it in one of the comments. Simple miscommunication. Between all 3 of us. In either case - the solution has been found. – Colin M Feb 05 '13 at 20:21
  • @ColinMorelli You are being quite rude and obtuse. It's like you are threatened or something. If you had read the OP's original example, you would have seen that he was confused why his echo statements weren't producing what he wanted in his json_encode. I addressed that by showing him why it wasn't in the structure he expected, and showing him that the data did actually exist a level up. In the future, this will allow the OP to debug his own code, and produce the proper structure. – crush Feb 05 '13 at 20:22
  • 1
    @crush Alright - you can argue with my apology. I gave it a shot. Good work on your answer. Thanks. – Colin M Feb 05 '13 at 20:24
0

Why not use that method, and then reconstruct the array you want at the end?

$results = array();
foreach ($arr as $id=>$amount) {
    $results[] = array('id' => $id, 'amount' => $amount);
}

Any other way of doing this would be more computationally expensive.

Colin M
  • 13,010
  • 3
  • 38
  • 58
  • This doesn't produce the desired result at all. – localheinz Aug 10 '17 at 13:11
  • As the answer indicates, this method does not sum the items, because the original question already does that. It simply re-constructs the array to get it back into the format the OP asked for. It certainly does produce the desired result, if - as the answer states - using the method the OP already started with. – Colin M Aug 11 '17 at 13:20
  • See https://d26dzxoao6i3hh.cloudfront.net/items/1H472z3c1D3U071g3V3W/Screen%20Shot%202017-08-10%20at%2015.13.23.png. – localheinz Aug 11 '17 at 13:22
  • I have no idea what I'm looking at. Given an associative array of `id => value`, this method most certainly reconstructs the array the OP asked for. Once again, this answer does nothing with summing results because the OP has _already_ done that. – Colin M Aug 11 '17 at 13:26