Plot highcharts heatmap graph - php

Below is rest api json output.
{
"data": {
"AB": [
{
"month": "Nov 2016",
"total_tax": "132"
},
{
"month": "Dec 2016",
"total_tax": 88
}
],
"BC": [
{
"month": "Nov 2016",
"total_tax": "132"
},
{
"month": "Dec 2016",
"total_tax": 76
}
],
"MB": [
{
"month": "Nov 2016",
"total_tax": "84"
},
{
"month": "Dec 2016",
"total_tax": 12
}
]
}
}
Above response is pass to jquery ajax function to plot highchart heatmap graph.We are trying to parse ajax response data to get the below pattern for heatmap graph.
var xaxisCategory = ['AB','BC','MB'];
var yaxisCategory = ['Nov 2016', 'Dec 2016'];
var series = [
[0, 0, 132], [0, 1, 88],
[1, 0, 132], [1, 1, 76],
[2, 0, 84], [2, 1, 12]
];
By using jquery inArray getting distinct x-axis and y-axis category.In series pattern having [x-axis,y-axis,value].In x-axis having 'AB' index is '0',on y-axis 'Nov 2016' index is '0' and values is total_tax is '132'.So how to plot series data.HoW to plot cartesian series data please help.

Try below example
var data = {
"data": {
"AB": [
{
"month": "Nov 2016",
"total_tax": 132
},
{
"month": "Dec 2016",
"total_tax": 88
}
],
"BC": [
{
"month": "Nov 2016",
"total_tax": 132
},
{
"month": "Dec 2016",
"total_tax": 76
}
],
"MB": [
{
"month": "Nov 2016",
"total_tax": 84
},
{
"month": "Dec 2016",
"total_tax": 12
}
]
}
};
var parsedata = data.data;
var xaxisCategory = Array();
var yaxisCategory = Array();
var series = Array();
jQuery.each( parsedata, function( key, value ) {
xaxisCategory.push(key);
jQuery.each( value, function( key, value ) {
yaxisCategory.push(value.month);
series.push(value.total_tax);
});
});
console.log(xaxisCategory);
console.log(yaxisCategory);
var final = Array();
var i = 0;
$.each(series, function( index, value ) {
var item = Array();
item.push(i);
if (index % 2 == 0) {
item.push(0);
}
else {
item.push(1);
}
if (index % 2 != 0) {
i++;
}
item.push(value);
final.push(item);
});
console.log(final);
Here is the jsfiddle see output in console

Related

How to group data by time period?

I have data on invoices and I want to group them by time period wall. for example 0-10 and 11-20:
I need to solve them with $aggregate in mongoDB.
{
'_id': '1',
'value': 10,
'due_date': '20221001'
},
{
'_id': '2',
'value': 10,
'due_date': '20221012'
},
{
'_id': '2',
'value': 10,
'due_date': '20221030'
},
I need to group by period 0-10 days, 11-20 days and sum the values: For the example above the result would be:
[{
"_id": '0-10 days',
"total": 10,
},
{
"_id": '11-20 days',
"total": 10,
},
{
"_id": '>20 days',
"total": 10,
}]
I try with:
['$facet' => [
['due_date_one' => [
['$match' => [
'due_date' => [
'$gt' => new UTCDateTime((new Carbon())-> subDays(100) -> getTimestamp()),
'$lte' => date('Y-m-d', strtotime('now'))
]
]
]],
]]
You could use $bucket or add a few $addFields and $group stages:
Example mongo playground - https://mongoplayground.net/p/B0zl_GGH4sG
Example Documents:
[
{
"_id": "1a",
"value": 10,
"due_date": "20221001"
},
{
"_id": "1b",
"value": 5,
"due_date": "20221102"
},
{
"_id": "1c",
"value": 7,
"due_date": "20221102"
},
{
"_id": "2a",
"value": 10,
"due_date": "20221012"
},
{
"_id": "2b",
"value": 7,
"due_date": "20221113"
},
{
"_id": "2c",
"value": 8,
"due_date": "20221113"
},
{
"_id": "3a",
"value": 10,
"due_date": "20221030"
},
{
"_id": "3b",
"value": 9,
"due_date": "20221131"
},
{
"_id": "3c",
"value": 11,
"due_date": "20221131"
}
]
Aggregation query:
db.collection.aggregate([
{
$addFields: {
day: {
$toInt: { $substr: [ "$due_date", 6, 2 ] }
}
}
},
{
$addFields: {
bucketDate: {
$switch: {
branches: [
{ case: { $gt: [ "$day", 20 ] }, then: ">20 days" },
{ case: { $gt: [ "$day", 10 ] }, then: "11-20 days" }
],
"default": "0-10 days"
}
}
}
},
{
$addFields: {
bucketDateWithMonth: {
$concat: [
{ $substr: [ "$due_date", 0, 6 ] },
" ",
"$bucketDate"
]
}
}
},
{
$group: {
//_id: "$bucketDate", //No grouped month
_id: "$bucketDateWithMonth", //With grouped month
count: { $sum: 1 },
value: { $sum: "$value" }
}
}
])
Output: (grouped month)
[
{
"_id": "202210 0-10 days",
"count": 1,
"value": 10
},
{
"_id": "202211 0-10 days",
"count": 2,
"value": 12
},
{
"_id": "202210 11-20 days",
"count": 1,
"value": 10
},
{
"_id": "202211 11-20 days",
"count": 2,
"value": 15
},
{
"_id": "202210 \u003e20 days",
"count": 1,
"value": 10
},
{
"_id": "202211 \u003e20 days",
"count": 2,
"value": 20
}
]
Output: (No grouped month)
[
{
"_id": "\u003e20 days",
"count": 3,
"value": 30
},
{
"_id": "0-10 days",
"count": 3,
"value": 22
},
{
"_id": "11-20 days",
"count": 3,
"value": 25
}
]

How do I add an item to the array taking into account the months of the year?

I have an response with this structure.
{
"records": [
{
"patientName": "CECILIA NONE ANCINEZ DE LOPEZ",
"patientProductCode": "MO000250",
"patientProduct": "RUXOLITINIB 15 MG TABLETA",
"patientFirstDispatch": "18/11/2021",
"dispatch": [
{
"month": 6,
"year": 2022,
"quantity": 30,
"period": "2022-6"
},
{
"month": 4,
"year": 2022,
"quantity": 30,
"period": "2022-4"
},
{
"month": 3,
"year": 2022,
"quantity": 30,
"period": "2022-3"
},
{
"month": 2,
"year": 2022,
"quantity": 30,
"period": "2022-2"
},
{
"month": 1,
"year": 2022,
"quantity": 30,
"period": "2022-1"
},
{
"month": 12,
"year": 2021,
"quantity": 30,
"period": "2021-12"
}
]
},
]
}
and I also have this json with the last 7 months.
{
"months": [
{
"month": "June",
"position": 6,
"year": 2022,
"period": "2022-6"
},
{
"month": "May",
"position": 5,
"year": 2022,
"period": "2022-5"
},
{
"month": "April",
"position": 4,
"year": 2022,
"period": "2022-4"
},
{
"month": "March",
"position": 3,
"year": 2022,
"period": "2022-3"
},
{
"month": "February",
"position": 2,
"year": 2022,
"period": "2022-2"
},
{
"month": "January",
"position": 1,
"year": 2022,
"period": "2022-1"
},
{
"month": "December",
"position": 12,
"year": 2021,
"period": "2021-12"
}
]
}
I need to add an object inside the dispatch array with the property
"quantity" = 0 when the "period" property doesn't match between the dispatch array and the months array.
the result of comparing between the array "months" and "dispatch" should return something like this.
An object was added at position 1 of the "dispatch" array.
{
"records": [
{
"patientName": "CECILIA NONE ANCINEZ DE LOPEZ",
"patientProductCode": "MO000250",
"patientProduct": "RUXOLITINIB 15 MG TABLETA",
"patientFirstDispatch": "18/11/2021",
"dispatch": [
{
"month": 6,
"year": 2022,
"quantity": 30,
"period": "2022-6"
},
{
"month": 5,
"year": 2022,
"quantity": 0,
"period": "2022-5"
},
{
"month": 4,
"year": 2022,
"quantity": 30,
"period": "2022-4"
},
{
"month": 3,
"year": 2022,
"quantity": 30,
"period": "2022-3"
},
{
"month": 2,
"year": 2022,
"quantity": 30,
"period": "2022-2"
},
{
"month": 1,
"year": 2022,
"quantity": 30,
"period": "2022-1"
},
{
"month": 12,
"year": 2021,
"quantity": 30,
"period": "2021-12"
}
]
},
]
}
I tried to do it but I could not add the objects correctly.
could you help me with this problem.
You can use forEach() and array_filter() for searching, then add new record to dispatch. Same as :
foreach ($objectMonths->months as $arrayMonth) {
foreach ($objectDispatch->records as $record) {
$exist = array_filter($record->dispatch, fn($mon) => $mon->period === $arrayMonth->period);
if (!count($exist)) {
$month = date('m', strtotime($arrayMonth->period));
$record->dispatch[] = (object)['month' => (int)$month, 'year' => $arrayMonth->year, 'quantity' => 0, 'period' => $arrayMonth->period];
usort($record->dispatch, fn($a, $b) => $a->period < $b->period);
}
}
}
Code sample in here

php query is not adding all data to jsonarray

i am new to PHP OOP , i have a database that contains products, the goal is to extract for every product grouped by ligne field all the months data of the products, after i executed the result i have been surprised that only the data of the month 8 is displayed while there are some products that have data in months like 4 or 6.
Here the database rows:
Here the json Result array and we can observe that some products qte in some months is displayed as zero while their qte is not zero in some cases
[
{
"id": "8",
"ligne": "Biscuit",
"produit": "Major",
"date": "2021-08-11",
"heure": "10:00",
"qte": "380",
"months": [
{
"month": 1,
"qte": 0
},
{
"month": 2,
"qte": 0
},
{
"month": 3,
"qte": 0
},
{
"month": 4,
"qte": 0
},
{
"month": 5,
"qte": 0
},
{
"month": 6,
"qte": 0
},
{
"month": 7,
"qte": 0
},
{
"month": 8,
"qte": 380
},
{
"month": 9,
"qte": 0
},
{
"month": 10,
"qte": 0
},
{
"month": 11,
"qte": 0
},
{
"month": 12,
"qte": 0
}
],
"year": "2021"
},
{
"id": "6",
"ligne": "Eau",
"produit": "Safia 1.5",
"date": "2021-08-11",
"heure": "14:00",
"qte": "320",
"months": [
{
"month": 1,
"qte": 0
},
{
"month": 2,
"qte": 0
},
{
"month": 3,
"qte": 0
},
{
"month": 4,
"qte": 0
},
{
"month": 5,
"qte": 0
},
{
"month": 6,
"qte": 0
},
{
"month": 7,
"qte": 0
},
{
"month": 8,
"qte": 320
},
{
"month": 9,
"qte": 0
},
{
"month": 10,
"qte": 0
},
{
"month": 11,
"qte": 0
},
{
"month": 12,
"qte": 0
}
],
"year": "2021"
},
{
"id": "12",
"ligne": "Lait",
"produit": "Vitalait 1/2",
"date": "2021-08-11",
"heure": "8:00",
"qte": "379",
"months": [
{
"month": 1,
"qte": 0
},
{
"month": 2,
"qte": 0
},
{
"month": 3,
"qte": 0
},
{
"month": 4,
"qte": 0
},
{
"month": 5,
"qte": 0
},
{
"month": 6,
"qte": 0
},
{
"month": 7,
"qte": 0
},
{
"month": 8,
"qte": 379
},
{
"month": 9,
"qte": 0
},
{
"month": 10,
"qte": 0
},
{
"month": 11,
"qte": 0
},
{
"month": 12,
"qte": 0
}
],
"year": "2021"
},
{
"id": "10",
"ligne": "Salami",
"produit": "Mazraa",
"date": "2021-08-11",
"heure": "8:00",
"qte": "570",
"months": [
{
"month": 1,
"qte": 0
},
{
"month": 2,
"qte": 0
},
{
"month": 3,
"qte": 0
},
{
"month": 4,
"qte": 0
},
{
"month": 5,
"qte": 0
},
{
"month": 6,
"qte": 0
},
{
"month": 7,
"qte": 0
},
{
"month": 8,
"qte": 570
},
{
"month": 9,
"qte": 0
},
{
"month": 10,
"qte": 0
},
{
"month": 11,
"qte": 0
},
{
"month": 12,
"qte": 0
}
],
"year": "2021"
},
{
"id": "4",
"ligne": "Yaourt",
"produit": "Delice",
"date": "2021-08-11",
"heure": "12:00",
"qte": "1020",
"months": [
{
"month": 1,
"qte": 0
},
{
"month": 2,
"qte": 0
},
{
"month": 3,
"qte": 0
},
{
"month": 4,
"qte": 0
},
{
"month": 5,
"qte": 0
},
{
"month": 6,
"qte": 0
},
{
"month": 7,
"qte": 0
},
{
"month": 8,
"qte": 1020
},
{
"month": 9,
"qte": 0
},
{
"month": 10,
"qte": 0
},
{
"month": 11,
"qte": 0
},
{
"month": 12,
"qte": 0
}
],
"year": "2021"
}
]
Here the Php Code :
public function getProductsStatsByMonths() {
$today = date("Y-m-d");
$date_arr = explode("-", $today);
$year = $date_arr[0];
$month = $date_arr[1];
$day = $date_arr[2];
$prods = array();
$months = array(
1 ,
2 ,
3 ,
4 ,
5 ,
6 ,
7 ,
8 ,
9 ,
10 ,
11 ,
12
);
$stmt = $this->conn->prepare("SELECT SUM(qte) as total , id ,ligne, produit, date, heure FROM production where YEAR(date) = ? GROUP BY LOWER(ligne) ");
$stmt->execute([$year]);
while( $row = $stmt->fetch(pdo::FETCH_ASSOC)){
$date_arrrow = explode("-", $row["date"]);
$rowmonth = $date_arrrow[1];
$ligne = $row["ligne"];
$produit = $row["produit"];
$p = new ProductionByMonth($row["id"],$row["ligne"],$row["produit"],$row["date"],$row["heure"],$row["total"],-1,$year);
$prodmonths = array();
foreach ($months as $month){
if(($rowmonth == $month) ){
array_push($prodmonths,new Months($month,(int) $row["total"]));
// array_push($prods, new ProductionByMonth($row["id"],$row["ligne"],$row["produit"],$row["date"],$row["heure"],$row["total"],$month,$year));
}else if ($rowmonth != $month){
array_push($prodmonths,new Months($month,0));
// array_push($prods, new ProductionByMonth($row["id"],$row["ligne"],$row["produit"],$row["date"],$row["heure"],0,$month,$year));
}
}
$p->months = $prodmonths;
array_push($prods,$p);
}
echo json_encode($prods);
}
My wish is to find a way to correctly extract all the correct qte in the json array for every product grouped by ligne field
I recommend grouping and aggregating the data entirely in the application. $grp is the core data structure. However, it needs a second pass for aggregation. Performance-wise, this is okay, as it is O(n).
I created a live example at http://road-to-eng.rlc.ninja/. I also recommend separating the aggregation logic from the presentation logic (unlike my implementation).
Here's the code:
<?php
// DB LOGIC
$pdo = new PDO("mysql:host=<redacted>;dbname=<redacted>", "<redacted>", "<redacted>");
$flig = $_POST["ligne"];
if (isset($flig) && $flig != "all") {
$sql = "select * from orders where ligne = ?;";
$params = [$flig];
} else {
$sql = "select * from orders;";
$params = [];
}
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$res = $stmt->fetchAll();
// GROUPING LOGIC
$lignes = [];
$grp = [];
foreach ($res as $ord) {
$mo = (int) substr($ord["date"], 5, 2);
$ligne = $ord["ligne"];
$lignes[$ligne] = null;
if (!isset($grp[$ligne])) {
$grp[$ligne] = [];
}
if (!isset($grp[$ligne][$mo])) {
$grp[$ligne][$mo] = [];
}
array_push($grp[$ligne][$mo], $ord);
}
$lignes = array_keys($lignes);
?>
<form action="" method="post">
<table>
<tr>
<td>
<select name="ligne">
<option value="all" selected>-- all --</option>
<?php foreach ($lignes as $l) { ?>
<option value="<?php echo $l ?>"><?php echo $l ?></option>
<?php } ?>
</select>
</td>
<td><input type="submit" /></td>
</tr>
</table>
</form>
<pre>
<?php
// PRESENTATION AND AGGREGATION LOGIC (tightly coupled, not good practice)
printf("<strong>YEAR %s</strong>\n", "2021");
printf("\n");
foreach ($grp as $ligne => $ords_of_mo) {
printf("%s\n", $ligne);
foreach ($ords_of_mo as $mo => $ords) {
printf("\t%s\n", date("M", mktime(0, 0, 0, $mo+1, 0, 0)));
// AGGREGATION LOGIC
$tot_qte = 0;
foreach ($ords as $o) {
$tot_qte += $o["qte"];
}
printf("\t\t%5s %10s %15s %15s %12s %10s\n", "id", "ligne", "produit", "date", "heure", "qte");
printf("\t\t========================================================================\n");
foreach ($ords as $o) {
printf("\t\t%5s %10s %15s %15s %12s %10s\n", $o["id"], $o["ligne"], $o["produit"], $o["date"], $o["heure"], $o["qte"]);
}
printf("\t\t%5s %10s %15s %15s %12s <strong>%10s</strong>\n", "", "", "", "", "", $tot_qte);
printf("\n");
}
}
?>
</pre>

Can't show stacked columns dynamic json data

Hi all i'm looking for help creating a test chart with dynamic data in php.
In first place i create the graph witout problem.
window.onload = function () {
chart = new CanvasJS.Chart("chartContainer", {
animationEnabled: true,
title:{
text: "Gasto Proyectado (neto)"
},
axisX: {
interval: 1,
intervalType: "month",
valueFormatString: "MM/YYYY"
},
axisY: {
suffix: "",
valueFormatString: "$#,###"
},
toolTip: {
shared: true
},
legend: {
reversed: true,
verticalAlign: "center",
horizontalAlign: "right",
cursor: "pointer",
itemclick: toggleDataSeries
},
data:[
<?php
$gastoMensualProyectado = Helper::gastoMensualProyectado();
//var_dump($gastoMensualProyectado);
//die();
$controlCostoN1= array();
foreach ($gastoMensualProyectado as $key => $value) {
$controlCostoN1[]= $value['name'];
}
$controlCostoN1 = array_unique($controlCostoN1);
$output = '';
foreach ($controlCostoN1 as $indice => $name) {
$output .= '{
type: "stackedColumn",
name: "'.$name.'",
showInLegend: true,
xValueFormatString: "MMM, YYYY",
yValueFormatString: "$#,###",
dataPoints:[';
foreach ($gastoMensualProyectado as $key => $value) {
if ($name == $value['name']){
$output.='{ x:'.$value['x'].', y:'.$value['y'].'},';
}
}
$output .=']},';
}
$output = substr($output,0,-3);
print $output;
?>
]
}]
});
chart.render();
Then i want to put new data calling a php file that respond with json_encode function
$dps = array();
$i=0;
$header = '';
foreach ($controlCostoN1 as $indice => $name) {
//$val[$i] = 'type: "stackedColumn",name: "'.$name.'",showInLegend: true,xValueFormatString: "MMM, YYYY",yValueFormatString: "$#,###",dataPoints:';
//var_dump($name);
foreach ($gastoMensualProyectado as $key => $value) {
// echo $name;
if ($name == $value['name']){
$dps[][$name] = $value;
/*
$header .= '{
type: "stackedColumn",
name: "'.$name.'",
showInLegend: true,
yValueFormatString: "#,##0 MW",
dataPoints: ';
//$points[] = '{ x:'.$value['x'].', y:'.$value['y'].'},';
//$dps[] = [ "x" => $value['x'], "y" => $value['y'] ];
.json_encode($value, JSON_NUMERIC_CHECK).'
},';
*/
}
}
}
// $output = substr($output,0,-3);
echo json_encode($dps);`
And then try to refresh the data in the graph when change a select but the grph change with no columns at all.
` $('#idPresupuesto').change(function(event) {
var dps = [];
var names = [];
var response;
$.getJSON("acciones/obtenerDatosStackedColumns.json.php", { idPresupuesto: $(this).val() } ,function(data) {
// console.log(data);
// console.log("swasaddsaasd");
$.each(data, function(key, value){
// dataPoints.push({x: value[0], y: parseInt(value[1])});
// console.log(value.first());
// console.log(value[Object.keys(value)[0]].name);
// value.map()
jQuery.map( value , function( n, i){
if(jQuery.inArray(n.name,names) < 0){
names.push(n.name);
//console.log(n.name);
}
});
});
$.each(data, function(key, value){
// console.log(key);
jQuery.map( value , function( n, i){
// console.log(n.x + " "+n.y);
dps.push({x: n.x, y: parseInt(n.y)});
// console.log();
});
});
console.log(dps);
// console.log(names);
// console.log(names.length);
var chart = new CanvasJS.Chart("chartContainer",{
title:{
text:"Presupuesto"
},
animationEnabled: true,
data: [{
dataPoints : dps,
}]
});
chart.render();
});
});`
the json response is:
[{
"Alimentaci\u00f3n": {
"idOrdenCompra": 7,
"x": "new Date(2019, 2)",
"y": 1361340,
"name": "Alimentaci\u00f3n"
}
}, {
"Alimentaci\u00f3n": {
"idOrdenCompra": 146,
"x": "new Date(2019, 2)",
"y": 60000,
"name": "Alimentaci\u00f3n"
}
}, {
"Equipos": {
"idOrdenCompra": 125,
"x": "new Date(2019, 1)",
"y": 350500,
"name": "Equipos"
}
}, {
"Equipos": {
"idOrdenCompra": 29,
"x": "new Date(2019, 3)",
"y": 95014016,
"name": "Equipos"
}
}, {
"Equipos": {
"idOrdenCompra": 141,
"x": "new Date(2019, 3)",
"y": 2743908,
"name": "Equipos"
}
}, {
"Equipos de Protecci\u00f3n Personal": {
"idOrdenCompra": 1,
"x": "new Date(2019, 1)",
"y": 26179454,
"name": "Equipos de Protecci\u00f3n Personal"
}
}, {
"Equipos de Protecci\u00f3n Personal": {
"idOrdenCompra": 18,
"x": "new Date(2019, 3)",
"y": 8599651,
"name": "Equipos de Protecci\u00f3n Personal"
}
}, {
"Equipos de Protecci\u00f3n Personal": {
"idOrdenCompra": 84,
"x": "new Date(2019, 3)",
"y": 3233271,
"name": "Equipos de Protecci\u00f3n Personal"
}
}, {
"Materiales": {
"idOrdenCompra": 4,
"x": "new Date(2019, 2)",
"y": 12975104,
"name": "Materiales"
}
}, {
"Materiales": {
"idOrdenCompra": 14,
"x": "new Date(2019, 2)",
"y": 30393814,
"name": "Materiales"
}
}, {
"Materiales": {
"idOrdenCompra": 82,
"x": "new Date(2019, 2)",
"y": 30014590,
"name": "Materiales"
}
}, {
"Saldos Gastos Generales": {
"idOrdenCompra": 3,
"x": "new Date(2019, 2)",
"y": 4657962,
"name": "Saldos Gastos Generales"
}
}, {
"Saldos Gastos Generales": {
"idOrdenCompra": 16,
"x": "new Date(2019, 3)",
"y": 107923647,
"name": "Saldos Gastos Generales"
}
}, {
"Saldos Gastos Generales": {
"idOrdenCompra": 86,
"x": "new Date(2019, 3)",
"y": 80498702,
"name": "Saldos Gastos Generales"
}
}, {
"Herramientas": {
"idOrdenCompra": 16,
"x": "new Date(2019, 3)",
"y": 5056052,
"name": "Herramientas"
}
}, {
"Herramientas": {
"idOrdenCompra": 92,
"x": "new Date(2019, 4)",
"y": 2192715,
"name": "Herramientas"
}
}, {
"Mano de Obra": {
"idOrdenCompra": 19,
"x": "new Date(2019, 1)",
"y": 16748410,
"name": "Mano de Obra"
}
}, {
"Mano de Obra": {
"idOrdenCompra": 91,
"x": "new Date(2019, 3)",
"y": 1962698,
"name": "Mano de Obra"
}
}]
Actually the first graph render good but when i try to update data show me an empty chart.
I fixed it changing the json content of date
"x": "new Date(2019, 3)",
to
"x": "2019, 3",
and then apply to this line the object Date
$output.='{ x:new Date('.$value['x'].'), y:'.$value['y'].'},';
the the graph works great an dynamically!
hope this help to somebody.

Sum values of same key that have same user id also retain there date as key

I am trying to add up the totalPlayed values for each user_id. I don't want to change the overall structure of the array, I just want to condense the events subarrays by summing the totalPlayed values.
Here is a sample array as json:
[
{
"date": "May 29",
"date_start": "2018-05-29 05:00:00",
"date_end": "2018-05-30 04:59:59",
"interval": 29,
"calDay": "29 days ago",
"events": [
{
"totalPlayed": 184,
"user_id": 479
},
{
"totalPlayed": 906,
"user_id": 479
},
{
"totalPlayed": 400,
"user_id": 1446
},
{
"totalPlayed": 500,
"user_id": 1446
}
]
},
{
"date": "May 30",
"date_start": "2018-05-30 05:00:00",
"date_end": "2018-05-31 04:59:59",
"interval": 28,
"calDay": "28 days ago",
"events": [
{
"totalPlayed": 1469,
"user_id": 1626
},
{
"totalPlayed": 1482,
"user_id": 1690
},
{
"totalPlayed": 1434,
"user_id": 1690
}
]
}
]
I would like this result:
array (
0 =>
array (
'date' => 'May 29',
'date_start' => '2018-05-29 05:00:00',
'date_end' => '2018-05-30 04:59:59',
'interval' => 29,
'calDay' => '29 days ago',
'events' =>
array (
0 =>
array (
'totalPlayed' => 1090,
'user_id' => 479,
),
1 =>
array (
'totalPlayed' => 900,
'user_id' => 1446,
),
),
),
1 =>
array (
'date' => 'May 30',
'date_start' => '2018-05-30 05:00:00',
'date_end' => '2018-05-31 04:59:59',
'interval' => 28,
'calDay' => '28 days ago',
'events' =>
array (
0 =>
array (
'totalPlayed' => 1469,
'user_id' => 1626,
),
1 =>
array (
'totalPlayed' => 2916,
'user_id' => 1690,
),
),
),
)
I tried the following function but it is not working for me.
function computeOutcome($array) {
$result=array();
foreach ($array as $item) {
$id=$item['user_id'];
if (isset($result[$id])) {
$result[$id]=$result[$id]+$item['time_played'];
} else {
$result[$id]=$item['time_played'];
}
}
return $result;
}
Using temporary keys on your deep subarrays offers improved performance versus iterated in_array() calls. See inline comments for more explanations.
Code: (Demo)
function computeOutcome($array) {
foreach ($array as &$set) { // modify by reference
$tmp = []; // use a fresh temporary array for each date-set
foreach ($set['events'] as $record) {
$id = $record['user_id'];
if (isset($tmp[$id])) {
$tmp[$id]['totalPlayed'] += $record['totalPlayed']; // increase the tally
} else {
$tmp[$id] = $record; // store the whole row
}
}
$set['events'] = array_values($tmp); // remove temporary keys
}
return $array;
}
$json = <<<JSON
[
{
"date": "May 29",
"date_start": "2018-05-29 05:00:00",
"date_end": "2018-05-30 04:59:59",
"interval": 29,
"calDay": "29 days ago",
"events": [
{
"totalPlayed": 184,
"user_id": 479
},
{
"totalPlayed": 906,
"user_id": 479
},
{
"totalPlayed": 400,
"user_id": 1446
},
{
"totalPlayed": 500,
"user_id": 1446
}
]
},
{
"date": "May 30",
"date_start": "2018-05-30 05:00:00",
"date_end": "2018-05-31 04:59:59",
"interval": 28,
"calDay": "28 days ago",
"events": [
{
"totalPlayed": 1469,
"user_id": 1626
},
{
"totalPlayed": 1482,
"user_id": 1690
},
{
"totalPlayed": 1434,
"user_id": 1690
}
]
}
]
JSON;
var_export(computeOutcome(json_decode($json, true)));
Assuming your main array is called $data, this solution builds a new array with summed values, you can then replace the original array with the new one created:
function computeOutcome($array) {
$events = [];
foreach ($array as $evt) {
if (in_array($evt['user_id'], array_column($events, 'user_id'))) {
$key = array_search($evt['user_id'], array_column($events, 'user_id'));
$events[$key]['totalPlayed'] += $evt['totalPlayed'];
} else {
$events[] = $evt;
}
}
return $events;
}
$data['events'] = computeOutcome($data['events']);
EDIT:
As you have a JSON string, I got the same result as before doing this (assuming your JSON string is called $json):
$data = json_decode($json, true);
// Still using the function I wrote before
for ($i = 0; $i < count($data); $i++) {
$data[$i]['events'] = computeOutcome($data[$i]['events']);
}
// Print result
echo '<pre>' . print_r($data, true) . '</pre>';
Documentation:
in_array()
array_column()
array_search()
You can use array_column to find the user id, array_intersect to find the respective values and array_sum to sum the values.
$data =json_decode('
[
{
"date": "May 29",
"date_start": "2018-05-29 05:00:00",
"date_end": "2018-05-30 04:59:59",
"interval": 29,
"calDay": "29 days ago",
"events": [
{
"totalPlayed": 184,
"user_id": 479
},
{
"totalPlayed": 906,
"user_id": 479
},
{
"totalPlayed": 400,
"user_id": 1446
},
{
"totalPlayed": 500,
"user_id": 1446
}
]
},
{
"date": "May 30",
"date_start": "2018-05-30 05:00:00",
"date_end": "2018-05-31 04:59:59",
"interval": 28,
"calDay": "28 days ago",
"events": [
{
"totalPlayed": 1469,
"user_id": 1626
},
{
"totalPlayed": 1482,
"user_id": 1690
},
{
"totalPlayed": 1434,
"user_id": 1690
}
]
}
]', true);
Foreach($data as $key => $arr){
$userid = array_column($arr["events"], "user_id");
$played = array_column($arr["events"], "totalPlayed");
Foreach(array_unique($userid) as $id){
$temp = array_intersect_key($played, array_intersect($userid, [$id]));
$new[$key]['events']['date'] = $arr['date'];
$new[$key]['events'][] = ['total played' => array_sum($temp), 'user_id' => $id];
}
}
Var_dump($new);
https://3v4l.org/G1jKI
This will only loop the unique userids instead of the full array.
In the future you can post arrays as Json or as var_export and it will be much easier for us to help you.

Categories