Store record inside parent array - php

I have column date_added which has this format date 2017-02-09 08:45:48. I want to store all records of same month inside that specific month, like Feb month records should be inside Feb array. I'm trying following code.
$Res = array();
$query = $this->pdoConnection->prepare("select id,date from `record` ");
$query->execute();
header("Content-type: application/json; charset=utf-8");
$month = array(1,2,3,4,5,6,7,8,9,10,11,12);
while ($row = $query->fetch(PDO::FETCH_ASSOC)) {
$Data = $row;
$array_date = date("m", strtotime($row['date']));
$alpha_month = date("M", strtotime($row['date']));
if(in_array($array_date,$month)){
$Res[] = array($alpha_month=>array($Data));
}
}
$output = array(
'response' => $Res
);
echo json_encode($output,JSON_PRETTY_PRINT);
Result
{
"response": [
{
"Jan": [
{
"id": "1",
"date_added": "2017-01-03 08:43:09"
}
]
},
{
"Feb": [
{
"id": "4",
"date_added": "2017-02-04 10:53:44"
}
]
},
{
"Feb": [
{
"id": "2",
"date_added": "2017-02-12 08:59:15"
}
]
}
]
}
As you can see my code is return separate array of Feb, but i wanted to store both of inside Feb array. I have tried different logic but still facing same issue.

A little bit more detailed to my short comment above:
Instead $Res[] = array($alpha_month=>array($Data)); you could do $Res[$alpha_month][] = $Data;
Currently you're fetching all result tuples in this while loop which is accurate and okay. But if you want to "group" some results in an array, one way to go with is:
$Res[$alpha_month][] = $Data;
With this code you're "pushing" the result ($Data) in your $Res array. The important part is the first array layer $Res[$alpha_month] which relates to the new structure:
array('JAN', 'FEB', ...);
The second [] declares for the first layer, in this case it's your month group, another array. You may will get PHP WARNINGS by pushing your result for every month in the first time, because $Res[$alpha_month][] leads to a two-level declaration inside your array.
In the first declaration, as mentioned earlier, you're pushing all groups / months into the array! But in the same time, php expects the first iterative, to be an array as well: ($Res[$alpha_month][])
So the clean solution would be the following:
if(!isset($Res[$alpha_month])){
$Res[$alpha_month] = array(); // You can also use []; instead array();
}
$Res[$alpha_month][] = $Data;
With that snippet, you're first checking the $Res[$alpha_month] for existence - which also declares an array, if the current layer is not available.

You can try
$Res[$alpha_month][] = $data;
That will just add an entry to your array for that month, you also don't need the if(in_array($array_date,$month)) anymore

Related

How to remove values from an array in Laravel

I am trying to make a really basic day booking system and need to return all dates within a range, and then remove selected dates from that range. I tried the following code but realised that will remove duplicates which is fine, but I also need that date to be removed too.
Can anyone suggest a good way of doing this?
In the below example I am just hoping to see:
2022-04-03T00:00:00.000000Z
2022-04-04T00:00:00.000000Z
2022-04-05T00:00:00.000000Z
$start_date = "2022-04-01";
$end_date = "2022-04-05";
$datesToRemove = [
'2022-04-01T00:00:00.000000Z',
'2022-04-02T00:00:00.000000Z'
];
$range = Carbon::parse($start_date)->toPeriod($end_date)->toArray();
$available = array_unique(array_merge($range, $datesToRemove));
return $available;
To compare it is necessary to have the compared values in the same format. I decide to morph the $datesToRemove to Carbon format. The you can use to nested loops and check with PHP in_array() function.
$start_date = "2022-04-01";
$end_date = "2022-04-05";
$datesToRemove = [
"2022-04-01T00:00:00.000000Z",
"2022-04-02T00:00:00.000000Z"
];
$range = \Carbon\Carbon::parse($start_date)->toPeriod($end_date)->toArray();
$datesToRemove2 = [];
foreach($datesToRemove as $r) {
$datesToRemove2[] = \Carbon\Carbon::parse($r);
}
$res = [];
foreach($datesToRemove2 as $index => $d1) {
if(in_array($d1, $range)) {
unset($range[$index]);
}
}
return $range;
output
{
"2":"2022-04-03T00:00:00.000000Z",
"3":"2022-04-04T00:00:00.000000Z",
"4":"2022-04-05T00:00:00.000000Z"
}
Means that

How can I access Json information in php using array indexing

I want to get all prices and add them. I was planning on using this to loop through the JSON but that would be another question. Am I approaching this the wrong way? Is there a better way to get the SUM of all prices?
I have found this answer which makes the same question but it does not work (duplicate: PHP: How to access array element values using array-index). Here is my JSON string.
{
"data": {
"230723": {
"2019-11-15": {
"price": 52,
"min_length_of_stay": 2,
"available": 1
},
"2019-11-16": {
"price": 90,
"min_length_of_stay": 2,
"available": 0
},
"2019-11-17": {
"price": 44,
"min_length_of_stay": 2,
"available": 0
},
"2019-11-18": {
"price": 44,
"min_length_of_stay": 2,
"available": 0
}
}
}
}
And here is my code:
$resultJson = file_get_contents('http://....');
$priceRange = json_decode($resultJson, true);
echo $priceRange['data']['230723']['2019-11-15']['price']; // working
//$priceRange = array_values($priceRange);
echo $priceRange[0][0][0][0]; // not working
The first echo works and return 52. The second echo does not work with or without the commented line (which was the answer to the duplicate question).
What am I missing?
Instead of changing the array from associative to numeric just loop through already existing array
Like this
$sum = 0;
$resultJson = file_get_contents('http://....');
$priceRanges = json_decode($resultJson, true);
foreach ($priceRanges['data'] as $id => $priceRange) {
if (!is_array($priceRange)) {
continue;
}
foreach ($priceRange as $date => $priceInfo) {
$sum += (isset($priceInfo['price']) ? intval($priceInfo['price']) : 0);
}
}
Well you know I hope that the data is in data and if you don't know the next key then reset helps. Then just get all price keys (hopefully you know this as well) and sum them:
$result = array_sum(array_column(reset($array['data']), 'price'));
Another way is using array_values on the first two levels:
$result = array_sum(array_column(array_values(array_values($array)[0])[0], 'price'));
To get each price the way you were trying to do you would need:
$result = array_values(array_values(array_values(array_values($array)[0])[0])[0])[0];
The code I wrote using Krzysztof Janiszewski answer, and works.
$sum = 0;
$priceRange = json_decode($resultJson, true);
foreach($priceRange as $item) {
foreach($item as $item2){
foreach($item2 as $item3){
$sum += $item3['price'];
}
}
}
echo $sum;

How to get a value from nested json in php

I am a beginner to JSON and i'm trying to get values from a json string. For example i want to read the first "t":1443502800 and assing it to a variable $beginTime and the second "t":1443790800 assigned to a variable $endTime
{
"op":"&",
"c":[
{
"type":"date",
"d":">=",
"t":1443502800
},
{
"type":"date",
"d":"<",
"t":1443790800
}
],
"showc":[true,true]
}
I would really appreciate any help :)
Edit code
foreach($rs2 as $record2)
{
if( $record2->availability == '{"op":"&","c":[],"showc":[]}'){
//skip, because the restriction date was not set for this attendance
}
else{
//get the restriction date by making use of json
$json_data = json_decode($record2->availability, true);
echo $json_data['c'];
}
}
You were almost there. The full call should be to
$beginTime = $json_data['c'][0]['t'];
since $json_data['c'][0] is the array:
array (
"type" => "date",
"d" => ">=",
"t" => 1443502800
),
The $endtime can be obtained in a similar manner:
$endTime = $json_data['c'][1]['t'];
The problem is you can't echo an array. You're trying to echo out $json_data['c'], which is an array. Either return it or echo out what you need. For instance to echo out the start time use echo $json_data['c'][0]['t']
ORIGINAL ANSWER
You should use json_decode without true in the second variable. Then you have objects (started with braces {) and arrays (started with square brackets [). You can then get the start and end times us
<?php
$string = '{
"op":"&",
"c":[
{
"type":"date",
"d":">=",
"t":1443502800
},
{
"type":"date",
"d":"<",
"t":1443790800
}
],
"showc":[true,true]
}';
$json = json_decode($string);
echo "Start time: ".$json->c[0]->t;
echo "End time: ".$json->c[1]->t;
Here's an eval.in of it working - https://eval.in/441599

Given an array, find zero values and replace them with the average of immediately bordering values

I have an array of temperature data by hour. Some hours have zero data instead of a temp. When graphing using Google Charts, the zero causes the line graph to plummet. My temporary fix was to replace the zero values with null, causing a break in the line graph. The ideal solution would be to take the values on either side of the zero, and average them. The array is in order by hour. Help?
$array = array(
"1AM" => "65",
"2AM" => "66",
"3AM" => "68",
"4AM" => "68",
"5AM" => "68",
"6AM" => "0",
"7AM" => "70",
"8AM" => "71",
"9AM" => "71",
"10AM" => "73",
);
Here's my script replacing the 0's with nulls:
$array = array ();
foreach($parsed_json->history->observations as $key => $value) {
$temp = (int)$value->tempi;
if ($temp==0) {
str_replace(0, null, $temp);
}
$hour = $value->date->hour;
$array[$hour] = $temp;
};
This Example would work great if the data was mine, but alas, it's from a JSON feed.
Would I use an array_walk() sort of deal? How would I reference the current place in the array? Any help is appreciated!
I would scratch out the null portion, and just foreach-loop through the final array.
So, change your current code to:
$array = array ();
foreach($parsed_json->history->observations as $key => $value) {
$temp = (int)$value->tempi;
}
$hour = $value->date->hour;
$array[$hour] = $temp;
And add this below it:
foreach($array as $hour => $temp){
if($temp == "0"){
$numHour = $hour[0];
$hourPlus = ($numHour + 1) . "AM";
$hourMinus = ($numHour - 1) . "AM";
$valuePlus = $array[$hourPlus];
$valueMinus = $array[$hourMinus];
$average = ($valuePlus + $valueMinus)/2;
$array[$hour] = $average;
}
}
?>
This of course assumes that the values on either side of the zero are also not zero. You may want to add a check for that somewhere in there.
Tested and proven method.
Couldn't you do something along the lines of:
str_replace(0, ((($key-1)+($key+1))/2), $temp);
Where $key is array position, take the value before 0 and after 0 add them and divide them by 2 to get the average.
I'll let you sort out what happens if first, last or consecutive values are 0.
$the_keys=array_keys($array);
foreach($the_key as $index=>$key)
{
if($array[$key]==0)
{
$array[$key]=($array[$the_key[$index-1]]+$array[$the_key[$index+1]]/2);
}
}

Getting running average for PHP arrays

I'm using a series of MySQL queries to pull back calculations stored by date for graphing via the Flot library. After the calculations are done, the echoed material looks like this (using UNIX timestamp dates):
Item 1:
[
[1159765200000,-117.875],
[1159851600000,-117.25],
[1159938000000,-120.625],
[1160024400000,-122.125],
[1160110800000,-118.125],
[1160370000000,-121.125],
[1160456400000,-123.375],
[1160542800000,-115.625],
[1160629200000,-117.75],
[1160715600000,-112.75],
[1160974800000,-125.25],
[1161061200000,-135],
[1161147600000,-138.375],
[1161234000000,-137],
[1161320400000,-136.25],
[1161579600000,-139.875],
[1161666000000,-146.625],
[1161752400000,-143.625],
[1161838800000,-150.25],
[1161925200000,-152.875],
[1162188000000,-151.75],
[1162274400000,-149.75]
]
Item 2:
[
[1104732000000,47.3913043478],
[1104818400000,45.5072463768],
[1104904800000,45.5797101449],
[1104991200000,45.115942029],
[1105077600000,44.1739130435],
[1105336800000,44.5362318841],
[1105423200000,45.9565217391],
[1105509600000,45.9420289855],
[1105596000000,46.0289855072],
[1105682400000,46.4347826087],
[1106028000000,48.347826087],
[1106114400000,46.8695652174],
[1106200800000,46.4927536232],
[1106287200000,45.6376811594],
[1106546400000,44.3768115942],
[1106632800000,44.0579710145],
[1106719200000,44.5942028986],
[1106805600000,45.0289855072],
[1106892000000,45.231884058],
[1107151200000,46.1449275362],
[1107237600000,46.5942028986],
[1107324000000,45.5652173913],
[1107410400000,45],
[1107496800000,46.2608695652],
[1107756000000,45.7391304348],
[1107842400000,46.3333333333]
]
Basically I'd like to calculate the average of the second value in each pair, controlling for the date. In other words, for each date that matches in each array, print the date and the average of all the second values in each array, e.g:
[Common Date, Average of all second values]
I've looked through a number of array merging techniques but can't seem to find a workable solution.
Thanks very much for any help.
You could construct an array indexed by date in which you put a list of all values for the date:
$byDate = array();
foreach($item1 as $row) {
$date = sprintf('%.0f', $row[0]);
$byDate[$date][] = $row[1];
}
foreach($item2 as $row) {
$date = sprintf('%.0f', $row[0]);
$byDate[$date][] = $row[1];
}
Then you can easily compute the average for each list:
foreach($byDate as $date => $values) {
$avg = array_sum($values) / count($value);
printf("avg for %s: %f\n", $date, $avg);
}
Or compute all averages at once:
function array_avg($array) {
return array_sum($array) / count($array);
}
$avgByDate = array_map('array_avg', $byDate);
Try it here: http://codepad.org/1S1HrYoB
For your merge
$merged_array = array();
function merge_by_time()
{
$passed_arrays = func_get_args();
$merged_array = array();
foreach($passed_arrays as $array)
foreach($array as $value_set){
$merged_array[$value_set[0]][] = $value_set[1];
}
}
return $merged_array;
}
Usage:
$new_array = merge_by_time($array1, $array2, $array3, ...)
Then you'll have an array based on timestamp that has all associated data values contained in it. I think you can take it from here to get the averages?
Second approach
function merge_by_time_and_get_average()
{
$passed_arrays = func_get_args();
$merged_array = array();
foreach($passed_arrays as $array)
foreach($array as $value_set){
$merged_array[$value_set[0]]['data'][] = $value_set[1];
$merged_array[$value_set[0]]['average'] = 0;
foreach($merged_array[$value_set[0]]['data'] as $data_point){
$merged_array[$value_set[0]]['average'] += $data_point;
}
$merged_array[$value_set[0]]['average'] = $merged_array[$value_set[0]]['average']/count($merged_array[$value_set[0]]['data'])
}
}
return $merged_array;
}
Then you have $array[{timestamp}]['data'] containing your data points and $array[{timestamp}]['average'] containing your average of all data points. The nested foreachs are a little messy and expensive, but you can handle it all in one function call.

Categories