Crazy Serb
Crazy Serb

Reputation: 76320

Rewriting a JSON string - grouping keys by value into a new array?

Ok, I have a JSON string:

[{
"Name": "Title 1",
"Count1": 556,
"Count2": 5,
"Date": "2012-12-05"
}, {
"Name": "Title 2",
"Count1": 10,
"Count2": 100,
"Date": "2012-12-05"
}, {
"Name": "Title 3",
"Count1": 798,
"Count2": 11,
"Date": "2012-12-04"
}...

and I run json_decode on that, get an array, and now I want to run through that array and calculate totals for Count1 and Count2 for each date... (and the dates can go on for whatever range). What's the fastest/niftiest way of doing that?

Sort of loop through each key => val par in a foreach, and then somehow group the date keys into a new key in a new array and add the totals in there, so that I'm getting this as an output, in JSON feed at the very end, after json_encode, sorted by date:

[{
"Date": "2012-12-05"
"TotalCount1": 566,
"TotalCount2": 105,
}, {
"Date": "2012-12-04"
"TotalCount1": 798,
"TotalCount2": 11,
}...

how would I group the array values like that before sending the whole array to json_encode?

Upvotes: 1

Views: 1423

Answers (2)

benedict_w
benedict_w

Reputation: 3598

I think using a $totals array indexed on your date would work here (if I understand you correctly). Something like the example below where $data is your decoded associative JSON array:

$totals = array();

foreach ($data as $row) {
    if (isset($totals[$row['Date']]) ) {

        $totals[$row['Date']]['TotalCount1']
            = $totals[$row['Date']]['TotalCount1'] + $row['Count1'];

        $totals[$row['Date']]['TotalCount2']
            = $totals[$row['Date']]['TotalCount2'] + $row['Count2'];

    } else {

        $totals[$row['Date']] = array(
             'Date' => $row['Date'],
             'TotalCount1' => $row['Count1'],
             'TotalCount2' => $row['Count2'],
        );

    }
}

Upvotes: 2

Michael Berkowski
Michael Berkowski

Reputation: 270609

You will want to create an output array which is keyed by Date. Looping over each of your sub-arrays (or objects if that's what you have) from JSON, test if the date key already exists and add to it, or create it.

Lastly, call array_values() on it to strip off the Date keys and make it into a plain numeric-indexed array before encoding it back to JSON.

$output = array();
foreach ($original_array as $obj) {
  // If the date key ($obj->Date) already exists in the array, add the counts...
  if (isset($output[$obj->Date])) {
    $output[$obj->Date]->Count1 += $obj->Count1;
    $output[$obj->Date]->Count2 += $obj->Count2;
  }
  // Otherwise just append this object onto the output array
  // For objects, this must be cloned, since it would be saved as a reference otherwise.
  else {
    $output[$obj->Date] = clone $obj;
  }
}

// Then strip off the Date keys from the array:
// ready to call json_encode() on again...
$output = array_values($output);

The above assumes your original json_decode() call produced stdClass objects for the array elements, rather than associative arrays.

Here's a sample...

Upvotes: 2

Related Questions