How can I access Json information in php using array indexing - php

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;

Related

Looping php array to json prints index value

I have been trying to loop through an array. Inserting the values in two separate arrays $location and $name. But the $name array prints the index values as well, the $location works fine.
Here's a sample of code
$j = 0;
foreach( $entities->results as $key => $value ) {
if( stristr($value->vicinity, $key_stroke) ) {
$location[$j]['place_id'] = $value->place_id;
$location[$j]['vicinity'] = $value->vicinity;
}
if( stristr($value->name, $key_stroke) ) {
$name[$j]['place_id'] = $value->place_id;
$name[$j]['name'] = $value->name;
}
$j++; }
Here is the json output
{
"locations": [
{
"place_id": "ChIJRQqyYRFZWjcRmxKd0esyj-k",
"vicinity": "GS Road, Christian Basti, Guwahati"
},
{
"place_id": "ChIJG5IvxhNZWjcRlkMD6lCJ64c",
"vicinity": "GS Road, Ananda Nagar, Christian Basti, Guwahati"
},
{
"place_id": "ChIJxQp72BZZWjcR98oQbFrdTII",
"vicinity": "GS Road, Christian Basti, Guwahati"
},
{
"place_id": "ChIJm5eeJBBZWjcRksI_VY9u1Qo",
"vicinity": "Zoo Road, Sundarpur, Guwahati"
}
],
"names": {
"1": {
"place_id": "ChIJG5IvxhNZWjcRlkMD6lCJ64c",
"name": "Ayush Medico's"
},
"2": {
"place_id": "ChIJxQp72BZZWjcR98oQbFrdTII",
"name": "Premananda Medico's"
},
"3": {
"place_id": "ChIJm5eeJBBZWjcRksI_VY9u1Qo",
"name": "Asaan Medicos"
}
}
}
Tried everything. What could be the problem??
Solution 1: (Not efficient as the solution 2 below)
$j = 0;
$i = 0; // change over here
foreach( $entities->results as $key => $value ) {
if( stristr($value->vicinity, $key_stroke) ) {
$location[$j]['place_id'] = $value->place_id;
$location[$j]['vicinity'] = $value->vicinity;
$j++;
}
if( stristr($value->name, $key_stroke) ) {
$name[$i]['place_id'] = $value->place_id; // change over here
$name[$i]['name'] = $value->name; // change over here
$i++;
}
}
Solution 2:
Pass the $name array to php's inbuilt funtion array_values() which in turn will return you with the array index starting from 0.
If you look closely you will notice that in JSON, the value of "location" is an array but the value of "names" is an object (having the properties "1", "2" and "3"). This happens because $location is an array that contains 4 values associated with the keys 0, 1, 2 and 3 while $name is an array whose keys are 1, 2 and 3.
Because JSON is a subset of JavaScript and JavaScript arrays allow only numeric keys (starting from 0), PHP encodes as JavaScript arrays only the arrays that have numeric consecutive keys starting from 0. All the other arrays are encoded in JSON as objects.
This is written in the documentation of json_encode():
Note:
When encoding an array, if the keys are not a continuous numeric sequence starting from 0, all keys are encoded as strings, and specified explicitly for each key-value pair.
The reason why $names does not contain the key 0 is the if condition that wraps the assignment:
if( stristr($value->name, $key_stroke) ) {
The similar condition that wraps the assignment of $location[$j] can make $location behave similar with different input data.
If you want to get arrays in the JSON-encoded output you have to build them in a way that ensures the keys are consecutive integers starting with 0. This is easier than it sounds. There is no need to keep track of the keys, just build the inner arrays in a different way and let PHP generate the keys of the outer arrays:
$location = array();
$name = array();
foreach( $entities->results as $key => $value ) {
if( stristr($value->vicinity, $key_stroke) ) {
$location[] = array(
'place_id' => $value->place_id,
'vicinity' => $value->vicinity,
);
}
if( stristr($value->name, $key_stroke) ) {
$name[] = array(
'place_id' => $value->place_id,
'name' => $value->name,
);
}
}

Store record inside parent array

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

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);
}
}

Custom array sorting

At first - yes, I've tried to find my problem here, but can't make it.
I have a problem with array sorting. I want to use custom array sorting to sort some data taken from DB.
For example, I have array
values: [ 0, 0, 0, 0, 14830, 78426, 0, 0, 0, 0, 0, 0, 6024, 1144, 4438, 19282 ]
And I need to get last 4 (sometimes 3 or 2, so it would be custom) results on the first place in the same order as they are now. And the result should be like:
values: [ 6024, 1144, 4438, 19282, 14830, 78426, 0, 0, 0, 0, 0, 0,]
How can I do that?
I make this array with
while($row=mysql_fetch_array($re))
{
$dates = $row['mon'];
while ($current_month != $dates) {
$current_month = $current_month + 1;
if($current_month == 13)
$current_month = 1;
$data[] = 0;
}
$data[] = intval($row['type']);
$current_month = $dates+1;
}
I take months number as $current_month and using it puts my data in right places. When month have no results it adds 0 in that place.
The results should be just 6 and when there's no passing through the years it makes array right, but sometimes it goes wrong like this, so I want to make proper array using custom sorting like I mantioned at first.
So I want to sort this array and with array_slice cut it to 6.
Thanks for help.
$desired_length = 4;
$arr = array(1,2,3,4,5,6,7,8,9,10,11,12,13,14);
$length = count($arr);
$array = array_slice($arr, $length-$desired_length, $desired_length) + array_slice($arr,0,$length-$desired_length);
here is an exmaple of custom sort.. I am not sure if I understood your question correctly to help you there.. but this should give u an idea..
var myMultiArray = [ {"Name": "Steve", "Age":41},
{"Name": "Joe", "Age":55},
{"Name": "Robert", "Age":34},
{"Name": "Alex", "Age":35}];
function customMultiSort(a, b) {
return (a['Age'] - b['Age']);
}
myMultiArray.sort(customMultiSort);
document.write(myMultiArray.toSource());
$svalues = array_slice($values, 4);
rsort(&$svalues);
$array = array_merge(array_slice($values, count($values) - 4, 4), $svalues);

Find min/max values in a multidimensional array

I need to find the minimum and maximum in a multidimensional array in PHP, I have what I thought would work below but it keeps giving me a parse error, this is homework and I am not asking anyone to do it for me but I am a beginner and any help would be appreciated.
<?php
/* 2 dimensional array in PHP - strictly an array of arrays */
$multable[] = array("11", "12", "15", "22", "41", "42");
$multable[] = array("6", "7", "16", "17", "22", "23");
$multable[] = array("1", "15", "16", "20", "22", "3");
<table>
<?php
/* display a table from a 2D array */
for ($j=0;$j<3;$j++) {
print "<tr>";
for ($k=0;$k<6;$k++) {
echo "<td>",$multable[$j][$k],"</td>";
}
print "</tr>";
$max_value = 0;
foreach ($multable as $myMax) {
if ($max_value<$myMax) {
$max_value = $myMax;
}
}
echo $max_value;
?>
</table>
There is also a one-liner for that:
$max = max( array_map("max", $multable) );
use max() and min() functions of php.
Max:
<?php
$multable = array();
$multable[] = array("11", "12", "15", "22", "41", "42");
$multable[] = array("6", "7", "16", "17", "22", "23");
$multable[] = array("1", "15", "16", "20", "22", "3");
$max = -99999999;
foreach($multable as $sub){
$tempMax = max($sub);
if($tempMax > $max){
$max = $tempMax;
}
}
echo $max;
?>
You can figure out min :)
Your foreach iteration only does one dimension - each $myMax is one of your six element lists and not an individual scalar value. That's why your comparison doesn't work and the conditional is never true, you are trying to compare a scalar with an array. What you call $myMax would more appropriately be called $currentRow
This is ok because PHP has some functions to find the min and max of an array
http://us.php.net/manual/en/function.min.php
http://us.php.net/manual/en/function.max.php
$max_value = 0; $min_value = $multable[0][0];
foreach ($multable as $currentRow)
{
// COMPARE CURRENT ROW's MIN/MAX TO MIN/MAX_VALUE
// AND MAKE NEW ASSIGNMENT IF APPROPRIATE
}
Or hand this in and see what your teacher says:
function fComp ($f) {return function ($a,$b) use ($f) {return $f($a, $f($b));};}
$max = array_reduce($multable, fComp('max'), $multable[0][0]);
$min = array_reduce($multable, fComp('min'), $multable[0][0]);
echo "max: $max <br />";
echo "min: $min";
PS - in your earlier iterations to make the HTML table, it would be good form to lose the constants. Use count to get the length of the array instead - or better yet - use foreach like you do later on. (Even with foreach you would still need two of them nested, it doesn't iterate a 2-dimensional array element-by-element)
For Minimum value
echo min(array_map("min", $multable));
For Maximum Value
echo max(array_map("max", $multable));
$minArray = array();
foreach($arrayVal as $arrI=> $arrK)
{
if($arrK == min($arrayVal ) )
{
array_push($minArray , $arrayVal );
}
}
print_r($minArray);
Here you go :)
I do not recommend calling min() or max() on each subarray, then calling the function again on the reduced array. This is making too many calls and won't be most efficient.
Instead, flatten the indexed array just once with a spread&merge technique, then call min() or max() just once on the flattened array.
Code: (Demo)
$flat = array_merge(...$multable);
printf(
'Min: %d, Max: %d',
min($flat),
max($flat)
);
Output:
Min: 1, Max: 42
If you only need one or the other outcome, then don't bother with the temporary variable.
echo min(array_merge(...$multable));
Or
echo max(array_merge(...$multable));

Categories