Reputation: 5971
I have the following input:
$data = [
[
'date' => '2014-01-01',
'sales' => 1,
'price' => ['usd' => 1, 'eur' => 100],
],
[
'date' => '2014-01-05',
'sales' => 1,
'price' => ['usd' => 1, 'eur' => 100, 'gbp' => 500]
],
[
'date' => '2016-03-27',
'sales' => 5,
'age' => 50
],
[
'date' => '2016-03-28',
'sales' => 10
]
];
I need to sum the sales
column data and the child elements of the optionally occurring price
column per group to produce the following result:
$final = array(
'March 2016' => array(
'sales' => 15
),
'January 2014' => array(
'sales' => 2,
'price' => array(
'usd' => 2,
'eur' => 200,
'gbp' => 500
)
)
);
What I've done so far:
$monthlyData = array();
foreach ($dailyData as $day)
{
$key = date('M y', strtotime($day['date']));
if (!isset($monthlyData[$key]))
{
$monthlyData[$key] = $day;
continue;
}
foreach ($day as $metric => $value)
{
if(!empty($value))
{
$monthlyData[$key][$metric] += $value;
}
}
}
I know that we can use good ol' foreach
(with recursive calls) in order to get the right result, but I'm looking for some more elegant solution.
Upvotes: 2
Views: 110
Reputation: 35367
You really just need one more condition and loop for this specific example.
foreach ($day as $metric => $value)
{
/* Added Condition */
if(is_array($value))
{
foreach($value as $nestedMetric => $nestedValue) {
$monthlyData[$key][$metric][$nestedMetric] += $nestedValue;
}
}
elseif(!empty($value))
{
$monthlyData[$key][$metric] += $value;
}
}
Warning: A non-numeric value encountered
Warning: A non-numeric value encountered
Warning: Undefined array key "gbp"
Warning: A non-numeric value encountered
Warning: A non-numeric value encountered
array (
'Jan 14' =>
array (
'date' => 4028,
'sales' => 2,
'price' =>
array (
'usd' => 2,
'eur' => 200,
'gbp' => 500,
),
),
'Mar 16' =>
array (
'date' => 4032,
'sales' => 15,
'age' => 50,
),
)
However, I'd probably do it differently by handling the calculation based on the metric, not just treating every metric dynamically.
Upvotes: 1
Reputation: 48070
While iterating over the variably-populated items, reformat the date and remove the day-portion. Then push the sales data into its designated group in the result array; if re-encountering the group, add the current value to the stored value.
If the price
element has children, iterate over them and push them (or add them) to their designated element in the same fashion as described earlier.
Code: (Demo)
$result = [];
foreach ($data as $set) {
$group = (new DateTime($set['date']))->format('M Y');
$result[$group]['sales'] = ($result[$group]['sales'] ?? 0) + $set['sales'];
foreach ($set['price'] ?? [] as $currency => $amount) {
$result[$group]['price'][$currency] = ($result[$group]['price'][$currency] ?? 0) + $amount;
}
}
var_export($result);
Upvotes: 0