PHP: How to Group and Sum Up in Array - php

This is my array
array(
['studentId'=>"M100030","isbn"=>"0199535566",'price'=>"15.00"],
['studentId'=>"M100030","isbn"=>"0199535566",'price'=>"13.50"],
['studentId'=>"M100030","isbn"=>"0143105426",'price'=>"20.00"],
['studentId'=>"M100035","isbn"=>"1604501480",'price'=>"21.00"],
['studentId'=>"M100035","isbn"=>"1604501480",'price'=>"23.00"],
['studentId'=>"M100035","isbn"=>"0199535566",'price'=>"14.00"],
['studentId'=>"M103233","isbn"=>"0061964360",'price'=>"18.50"],
);
I want to group the studentId and isbn then sum up the price to JSON
{
"M100030":{
"0199535566":{
"amount":"28.50"
},
"0143105426":{
"amount":"20.00"
}
},
"M100035":{
"1604501480":{
"amount":"44.00"
},
"0199535566":{
"amount":"14.00"
}
},
"M103233":{
"0061964360":{
"amount":"18.50"
}
}
}
The method I tried so far to group the studentId and isbn, but not able to get the expected result. Anyone can correct my code?
foreach ($check['rentout'] as $key=> $values)
{
$keys = $values['studentId'];
if (!array_key_exists($keys,$trx)){
$trx[$keys] = array('isbn'=>$values['isbn'],'amount'=>$values['price']);
}else{
$trx[$keys]['amount'] = $trx[$keys]['amount']+$values['price'];
}
}

$students = array(
['studentId'=>"M100030","isbn"=>"0199535566",'price'=>"15.00"],
['studentId'=>"M100030","isbn"=>"0199535566",'price'=>"13.50"],
['studentId'=>"M100030","isbn"=>"0143105426",'price'=>"20.00"],
['studentId'=>"M100035","isbn"=>"1604501480",'price'=>"21.00"],
['studentId'=>"M100035","isbn"=>"1604501480",'price'=>"23.00"],
['studentId'=>"M100035","isbn"=>"0199535566",'price'=>"14.00"],
['studentId'=>"M103233","isbn"=>"0061964360",'price'=>"18.50"],
);
I Created variable $res and I looped over $students and get the $student_id and do a test if there is no isbn for this student, If So set their amount to the initial value, and loop again if we find it again accumulate its prices to amount, and do this again and again to all students in the array.
$res = [];
foreach ($students as $key => $student) {
$student_id = $student['studentId'];
if (!isset($res[$student_id][$student["isbn"]])){
$res[$student_id][$student["isbn"]]["amount"] = $student['price'];
}else{
$res[$student_id][$student["isbn"]]["amount"] += $student['price'];
}
}
echo "<pre>";
echo json_encode($res, JSON_PRETTY_PRINT);
Print(as excpected)
{
"M100030": {
"0199535566": {
"amount": 28.5
},
"0143105426": {
"amount": "20.00"
}
},
"M100035": {
"1604501480": {
"amount": 44
},
"0199535566": {
"amount": "14.00"
}
},
"M103233": {
"0061964360": {
"amount": "18.50"
}
}
}

Related

How to get sum of distinct key -> value in php arrays

I have the following string thatI convert into a json array. All I am trying to do put together keys with the same value for id_number and sum the amount to each of these keys and print the resulting value outside the loop.
$response = '{
"nhif":[
{
"id_number":"AA112233",
"amount":"5",
"date":"2018-09-14T20:18:50"
},
{
"id_number":"AA112233",
"amount":"5",
"date":"2018-09-14T19:59:14"
},
{
"id_number":"AA112233",
"amount":"5",
"date":"2018-09-14T09:07:34"
},
{
"id_number":"AA112233",
"amount":"5",
"date":"2018-09-14T09:04:27"
},
{
"id_number":"12345678",
"amount":"5",
"date":"2018-09-14T09:04:21"
}
]
}';
$json_response = json_decode($response, true);
//Start NHIF
foreach ($json_response['nhif'] as $nhif) {
echo ''.$nhif{"id_number"}.' '.$nhif{"amount"}.' '.$nhif{"date"}.'<br/>';
}
//END NHIF
My expected output is:
#id_number #amount
AA112233 20
12345678 5
Any workaround this?
You can use array_reduce to sum the amount values by id_number:
$sums = array_reduce($json_response['nhif'], function ($c, $i) {
$c[$i['id_number']] = (isset($c[$i['id_number']]) ? $c[$i['id_number']] : 0) + $i['amount'];
return $c;
}, array());
print_r($sums);
Output:
AA112233 20
12345678 5
Demo on rextester
If you're using PHP7, this
isset($c[$i['id_number']]) ? $c[$i['id_number']] : 0
can be simplified to
$c[$i['id_number']] ?? 0
You can do solve this problem using an array
$response = '{
"nhif":[
{
"id_number":"AA112233",
"amount":"5",
"date":"2018-09-14T20:18:50"
},
{
"id_number":"AA112233",
"amount":"5",
"date":"2018-09-14T19:59:14"
},
{
"id_number":"AA112233",
"amount":"5",
"date":"2018-09-14T09:07:34"
},
{
"id_number":"AA112233",
"amount":"5",
"date":"2018-09-14T09:04:27"
},
{
"id_number":"12345678",
"amount":"5",
"date":"2018-09-14T09:04:21"
}
]
}';
$json_response = json_decode($response, true);
$results = array(); // will map the unique keys with it's sum
//Start NHIF
foreach ($json_response['nhif'] as $nhif) {
if(!isset($results[$nhif['id_number']])) // new key initialized
$results[$nhif['id_number']] = $nhif['amount'];
else
$results[$nhif['id_number']] += $nhif['amount'];
}
//END NHIF
foreach($results as $key => $value) {
echo $key .' '.$value; // printing the result
}
Sort the array [If the data is not sorted otherwise do not need to sort].
Do the for loop and summation.
Try with this code sample, there are many other ways to solve this problem depending on problem solving skill.
$response = '{
"nhif":[
{
"id_number":"AA112233",
"amount":"5",
"date":"2018-09-14T20:18:50"
},
{
"id_number":"AA112233",
"amount":"5",
"date":"2018-09-14T19:59:14"
},
{
"id_number":"AA112233",
"amount":"5",
"date":"2018-09-14T09:07:34"
},
{
"id_number":"AA112233",
"amount":"5",
"date":"2018-09-14T09:04:27"
},
{
"id_number":"12345678",
"amount":"5",
"date":"2018-09-14T09:04:21"
}
]
}';
$data = json_decode($response, true);
usort($data['nhif'], function($a, $b) {
return $b['id_number'] <=> $a['id_number'];
});
//Start NHIF
$amount = 0;
$id_number = null;
foreach($data['nhif'] as $nhif) {
if(($nhif['id_number'] != $id_number) && ($id_number != null)){
echo $id_number. "\t". $amount . "<br />";
$id_number = $nhif['id_number'];
$amount = $nhif['amount'];
}
else{
$id_number = $nhif['id_number'];
$amount = $amount + $nhif['amount'];
}
// echo ''.$nhif{"id_number"}.' '.$nhif{"amount"}.' '.$nhif{"date"}.'<br />';
}
echo $id_number. "\t". $amount . "<br />";
//END NHIF
You could create a new array for example $r and check if the key for $nhif['id_number'] already exists.
If it does, add value for $nhif['amount']using +=. If it does not, set the value using =
This example uses the ternary ?: operator:
$r = [];
foreach ($json_response['nhif'] as $nhif) {
isset($r[$nhif['id_number']]) ? $r[$nhif['id_number']] += $nhif['amount'] : $r[$nhif['id_number']] = $nhif['amount'];
}
Demo

how to get json key name from the result in php?

I want to the key or reference_id detail (as both are same value) when the art_ean value contains 400004471.
{
"TD0000000000993": {
"reference_id": "TD0000000000993",
"art_ean": "400004481|,400004491|,400004471|"
},
"TD0000000000992": {
"reference_id": "TD0000000000992",
"art_ean": "400004482|,400004492|,400004472|"
}
}
Your json is not valid. You should remove the last , on each object. You can use a list to have some more details https://jsonlint.com.
Here is what I believe that you want.
<?php
$data = '{
"TD0000000000993": {
"reference_id": "TD0000000000993",
"art_ean": "400004481|,400004491|,400004471|"
},
"TD0000000000992": {
"reference_id": "TD0000000000992",
"art_ean": "400004482|,400004492|,400004472|"
}
}';
$decodedData = \json_decode($data, true);
$result = array_column(
array_filter($decodedData, function($data) {
return false !== strpos($data['art_ean'], '400004471');
}),
'reference_id'
);

PHP with Json + SQL

I'm having trouble correctly display, in JSON, a result originated from two tables in my database.
The situation is this: I have orders in a table (A) and the products these orders in another table (B).
My code:
$sqlcode2 = mysql_query("Select a.numero as numOrc, a.nomeclie, a.valortotal, a.formapagto, a.emissao, b.codprod, b.qtdade, b.valorunit, b.tipopreco from orcamento a, prodorc b");
$jsonObj= array();
if($something == 'all')
{
while($result=mysql_fetch_object($sqlcode2))
{
$jsonObj[] = $result;
$teste= array('pedidos' => $jsonObj);
}
}
$final_res =json_encode($teste);
echo $final_res;
The JSON result is like this:
{
"pedidos": [
{
"numOrc": "1",
"nomeclie": "CONSUMIDOR",
"valortotal": "2.077,20",
"formapagto": "2",
"emissao": "2013-02-15 16:09:11",
"codprod": "4775",
"qtdade": "1",
"valorunit": "500,00",
"tipopreco": "B"
},
{
"numOrc": "2",
"nomeclie": "MARCELO AUGUSTO BOTURA",
"valortotal": "2.077,20",
"formapagto": "2",
"emissao": "2013-02-15 16:21:56",
"codprod": "4775",
"qtdade": "1",
"valorunit": "500,00",
"tipopreco": "B"
}
]
}
As you can see, the result is only one product in each order. I needed the result to be as below (Detalhes TAG):
{
"pedidos": [
{
"numOrc": "2",
"nomeclie": "MARCELO AUGUSTO BOTURA",
"valortotal": "2.077,20",
"formapagto": "2",
"emissao": "2013-02-15 16:21:56",
"Detalhes":
[
{
"codprod": "4775",
"qtdade": "1",
"valorunit": "500,00",
"tipopreco": "B"
},
{
"codprod": "5555",
"qtdade": "3",
"valorunit": "800,00",
"tipopreco": "A"
}
]
}
]
}
A quick example of what FirstOne suggests would look like this. See how the orders are selected first and then a 2nd query is used to gather additional information about that order.
$sqlcode2 = mysql_query("Select a.numero as numOrc, a.nomeclie, a.valortotal, a.formapagto, a.emissao from orcamento a");
$jsonObj= array();
if($something == 'all')
{
while($result=mysql_fetch_object($sqlcode2))
{
$sqlcode3 = mysql_query("Select b.codprod, b.qtdade, b.valorunit, b.tipopreco
FROM prodorc b WHERE b.numOrc = " . $result->numOrc);
$Detalhes = array();
while($orderResult=mysql_fetch_object($sqlcode3))
{
$Detalhes[] = $orderResult;
}
$result->Detalhes = $Detalhes;
$jsonObj[] = $result;
}
}
$teste= array('pedidos' => $jsonObj);
$final_res =json_encode($teste);
echo $final_res;

MySQL to nested JSON

This is almost exactly what I want, but that question hasn't been answered and it's been a year. I've managed to get close, I think, but numbers are being printed as keys. In my example it shows up on line 47, but it is repeated for every "course_name" in the actual file.
[
{
"school_name": "Projects",
"terms": [
{
"term_name":"category_name#1",
"departments": [
{
"department_name":"sub_category_name1",
"department_code":"category code text here",
"courses":[
{
"course_name": "project1",
"course_code":"project 1 code text goes here",
"sections":[
{
"section_code":"mike",
"unique_id":"xxx#mail.com"
},
{
"section_code":"dan",
"unique_id":"xxx#gmail.com"
}
]
},
{
"course_name": "project2",
"course_code":"project 2 code text goes here",
"sections":[
{
"section_code":"steve",
"unique_id":"xxx#mail.com"
},
{
"section_code":"chris",
"unique_id":"xxx#gmail.com"
}
]
}
]
},
{
"department_name": "sub_category_name2",
"department_code":"sub category description text goes here..",
"courses": {
-->>> "69": {
"course_name": "project3",
"course_code":"project3 code text goes here ",
"sections":[
{
"section_code":"Alex",
"unique_id":"xxx#gmail.com"
}
]
}
}
}
]
}
]
}
]
Here is the query I am using and an example of data being returned.
SELECT school_name, term_name, department_name, department_code, course_code, course_name, section_code, magento_course_id
FROM schools INNER JOIN term_names ON schools.id=term_names.school_id INNER JOIN departments ON schools.id=departments.school_id INNER JOIN
adoptions ON departments.id=adoptions.department_id
"UCA-2" "SPRING 2013" "ACCOUNTING" "ACCT" "3315" "COST ACCOUNTING" "10258" 10311
What I have is being generated with this code.
$row_array = array();
$terms = array();
$departments = array();
$courses = array();
$h = 0;
$i = 0;
$j = 0;
while ($row = mysqli_fetch_assoc($fetch)) {
$row_array[$row['school_name']]['school_name'] = $row['school_name'];
$akey = array_search($row['term_name'], $terms);
if ($akey === FALSE) {
$m = $h++;
$terms[] = $row['term_name'];
$row_array[$row['school_name']]['terms'][$m]['term_name'] = $row['term_name'];
} else {
$m = $akey;
}
$key = array_search($row['department_code'], $departments);
if ($key === FALSE) {
$k = $i++;
$departments[] = $row['department_code'];
$row_array[$row['school_name']]['terms'][$m]['departments'][$k]['department_name'] = $row['department_name'];
$row_array[$row['school_name']]['terms'][$m]['departments'][$k]['department_code'] = $row['department_code'];
} else {
$k = $key;
}
$skey = array_search($row['course_code'], $courses);
if ($skey === FALSE) {
$l = $j++;
$courses[] = $row['course_code'];
$row_array[$row['school_name']]['terms'][$m]['departments'][$k]['courses'][$l]['course_name'] = $row['course_name'];
$row_array[$row['school_name']]['terms'][$m]['departments'][$k]['courses'][$l]['course_code'] = $row['course_code'];
} else {
$l = $skey;
}
$row_array[$row['school_name']]['terms'][$m]['departments'][$k]['courses'][$l]['sections'][] = array('section_code' => $row['section_code'], 'unique_id' => $row['magento_course_id']);
}
How do I generate this JSON without those numbers showing up?
I think you have some key & encoding problems. Too much key usage, excessive loops in your code. Maybe you should tidy your sql query.
Since you are setting keys for courses, JSON shows it.
Try removing the key after "['courses']" in your last line such as;
Change ['courses'][$l] to ['courses'][]
At the end, encode the array for JSON.
$result = json_encode($result);

Multiple MySQL table to json_encode

I have 3 different tables in my database called consoleConsole, consoleModel, and consoleGame. Then what I want to do is that each console will have a loop inside for its models, and each models will have another loop inside for its games like this:
[
{
"Console":"PlayStation",
"Information":[
{
"Model":"PlayStation 3",
"Title":[
{
"Game":"007 Legends",
"Publisher":"Electronic Arts"
},
{
"Game":"Ace Combat: Assault Horizon",
"Publisher":"Namco"
}
]
},
{
"Model":"PlayStation 2",
"Title":[
{
"Game":"007: Agent of Fire",
"Publisher":"Electronic Arts"
},
{
"Game":"Ace Combat 4: Shattered Skies",
"Publisher":"Namco"
}
]
},
{
"Model":"PlayStation 1",
"Title":[
{
"Game":"007 Racing",
"Publisher":"Electronic Arts"
},
{
"Game":"Ace Combat",
"Publisher":"Namco"
}
]
}
]
},
{
"Console":"Wii",
"Information":[
{
"Model":"Wii",
"Title":[
{
"Game":"007: Quantum of Solace",
"Publisher":"Activision"
},
{
"Game":"AC/DC Live: Rock Band Track Rack",
"Publisher":"MTV Games"
}
]
}
]
},
{
"Console":"Xbox",
"Information":[
{
"Model":"Xbox",
"Title":[
{
"Game":"AFL",
"Publisher":"Acclaim"
},
{
"Game":"American Chopper",
"Publisher":"Activision"
}
]
},
{
"Model":"Xbox 360",
"Title":[
{
"Game":"AFL Live",
"Publisher":"Electronic Arts"
},
{
"Game":"Akai Katana Shin",
"Publisher":"Cave"
}
]
}
]
}
]
But sadly, I was not using my database with this one but instead I just wrote it straight in a php file.
EDIT
Anyways, moving on. I have modified my code and ended up like this.
<?PHP
$consoleQuery = "SELECT * ".
"FROM consoleConsole ".
"JOIN consoleModel ".
"ON consoleConsole.consoleId = consoleModel.consoleId ".
"JOIN consoleGame ".
"ON consoleModel.modelId = consoleGame.gameId";
$consoleResult = mysql_query($consoleQuery);
$consoleFields = array_fill_keys(array(
'consoleName',
), null);
$modelFields = array_fill_keys(array(
'modelName',
), null);
$console = array();
$rowConsole = array();
while ($rowConsole = mysql_fetch_assoc($consoleResult)) {
$consoleId = $rowConsole['consoleId'];
$modelId = $row['modelId'];
if (isset($console[$consoleId]['Information'])) {
$console[$consoleId]['Information'][] = array_intersect_key($rowConsole, $modelFields);
}
else {
$console[$consoleId] = array_intersect_key($rowConsole, $consoleFields);
$console[$consoleId]['Information'] = array(array_intersect_key($rowConsole, $modelFields));
}
}
$console = array_values($console);
echo json_encode($console);
?>
I was able to produce an output but it doesn't look like the output above.
[
{
"consoleName": "PlayStation",
"Information": [
{
"modelName": "PlayStation"
},
{
"modelName": "PlayStation 2"
},
{
"modelName": "PlayStation 3"
},
{
"modelName": "PlayStation 3"
}
]
},
{
"consoleName": "Wii",
"Information": [
{
"modelName": "Wii"
},
{
"modelName": "Wii"
}
]
},
{
"consoleName": "Xbox",
"Information": [
{
"modelName": "Xbox"
},
{
"modelName": "Xbox 360"
}
]
}
]
Their relations:
What my problem is right now, I can't add the Title of the each Game.
Ok so I have written up your solution. You have to be sure that the order by is included there because it assumes that you are ordering them with there items together. I also didnt know how your publisher was stored so I separated that out into a separate table (this will allow you to then get items by just there publisher as well), which is now 4 joins. Also on another note I have updated it to do inner joins as well. This way you will not get empty results for consoles that don't have any games assigned to them. If you want these you could simply change the joins so that it would give you those results as well. Let me know if this helps
//get all of the information
$query = '
SELECT c.consoleId,c.consoleName,m.modelId,m.modelName,g.gameId,g.gameName,p.publisherId,p.publisherName
FROM `consoleconsole` c
INNER JOIN `consolemodel` m ON c.consoleId=m.consoleId
INNER JOIN `consolegame` g ON m.modelId=g.modelId
INNER JOIN `consolepublisher` p ON g.publisherId = p.publisherId
ORDER BY c.consoleName, m.modelName, g.gameName
';
//get the results
$result = mysql_query($query);
//setup array to hold information
$consoles = array();
//setup holders for the different types so that we can filter out the data
$consoleId = 0;
$modelId = 0;
//setup to hold our current index
$consoleIndex = -1;
$modelIndex = -1;
//go through the rows
while($row = mysql_fetch_assoc($result)){
if($consoleId != $row['consoleId']){
$consoleIndex++;
$modelIndex = -1;
$consoleId = $row['consoleId'];
//add the console
$consoles[$consoleIndex]['console'] = $row['consoleName'];
//setup the information array
$consoles[$consoleIndex]['information'] = array();
}
if($modelId != $row['modelId']){
$modelIndex++;
$modelId = $row['modelId'];
//add the model to the console
$consoles[$consoleIndex]['information'][$modelIndex]['model'] = $row['modelName'];
//setup the title array
$consoles[$consoleIndex]['information'][$modelIndex]['title'] = array();
}
//add the game to the current console and model
$consoles[$consoleIndex]['information'][$modelIndex]['title'][] = array(
'game' => $row['gameName'],
'publisher' => $row['publisherName']
);
}
echo json_encode($consoles);
Since you are using php function to encode json , it will give you the json in its default format. what you have to do is create your own function using string manipulation to get desired result.

Categories