PHP - get closest date from array - php

I want to get closest date from $search_date if is not same values in $array['date']. If is same value in $array['date'] I want all array.
Format date is 'Y-m-d'.
Example 1:
$search_date = '2022-12-08';
$array = [{"price":"200","date":"2022-12-12"},{"price":"50","date":"2022-12-10"},{"price":"100","date":"2022-12-10"}]
Return should be: [{"price":"50","date":"2022-12-10"},{"price":"100","date":"2022-12-10"}]
Example 2:
$search_date = '2022-12-08';
$array = [{"price":"200","date":"2022-12-08"},{"price":"50","date":"2022-12-09"},{"price":"100","date":"2022-12-11"}]
Return should be: [{"price":"200","date":"2022-12-08"}]
Example 3:
$search_date = '2022-12-08';
$array = [{"price":"200","date":"2022-12-10"},{"price":"100","date":"2022-12-10"},{"price":"50","date":"2022-12-11"}]
Return should be: [{"price":"200","date":"2022-12-10"},{"price":"100","date":"2022-12-10"}]
Example 4:
$search_date = '2022-12-08';
$array = [{"price":"200","date":"2022-12-08"},{"price":"100","date":"2022-12-08"},{"price":"50","date":"2022-12-08"}]
Return should be: [{"price":"200","date":"2022-12-08"},{"price":"100","date":"2022-12-08"},{"price":"50","date":"2022-12-08"}]
Thank you!

This code calculates the distance in days between $search and each record. It assumes that you want to find closest distance in both future and past.
<?php
/*
Question Author: Catalin Iamandei
Question Answerer: Jacob Mulquin
Question: PHP - get closest date from array
URL: https://stackoverflow.com/questions/74598442/php-get-closest-date-from-array
Tags: php, arrays, laravel, date, php-carbon
*/
$search = '2022-12-10';
$searchObj = new DateTime($search);
$records = json_decode('[{"price":"200","date":"2022-12-10"},{"price":"100","date":"2022-12-10"},{"price":"50","date":"2022-12-11"}]', true);
$distances = [];
foreach ($records as $index => $record) {
$recordObj = new DateTime($record['date']);
$daysDiff = $searchObj->diff($recordObj)->format("%r%a");
$distances[$index] = abs($daysDiff);
}
$minimumDiff = min($distances);
$output = [];
foreach ($distances as $index => $distance) {
if ($distance == $minimumDiff) {
$output[] = $records[$index];
}
}
echo json_encode($output, JSON_PRETTY_PRINT);
Yields:
[
{
"price": "50",
"date": "2022-12-09"
},
{
"price": "100",
"date": "2022-12-11"
}
]
If you only want to search for closest dates in the future, you need to remove the abs() function and then remove all negative entries in the $distances array before using min().

If you want to search for a specific value in your array have you tried
array_search($value, $array);
By this you can search for a specific value in your array
If you want to search the lowest value
try to for looping your array and check if the array is lower than the previous index and if the for loop has ended you have the lowest date
$lowest_date = null;
for ($i = 0; count($i); $i++) {
if ($array['date'] < $lowest_date) {
$lowest_date = $array['date'];
}
}

you dont have mentioned what todo with prior dates, eg. searching for '2022-12-07', how to tread 2022-12-06 and 2022-12-08, as the difference both is 1. You can calculate the datediff for each entry, get the min datediff and output elements with this datediff. eg :
<?php
$SearchDate = new DateTimeImmutable('2022-12-08');
$array = array ('{"price":"200","date":"2022-12-12"}',
'{"price":"50","date":"2022-12-10"}',
'{"price":"100","date":"2022-12-10"}');
$laResult = array();
foreach($array as $jsonO) {
$json = json_decode($jsonO);
$CompareDate = new DateTimeImmutable($json->{'date'});
$interval = date_diff($SearchDate, $CompareDate);
$laThis['date'] = $json->{'date'};
$laThis['diff'] = $interval->format('%a');
$laThis['origin'] = $jsonO;
$laResult[] = $laThis;
}
$min_diff = min( array_column( $laResult, 'diff') );
echo 'nearestDiff:'. $min_diff .PHP_EOL;
foreach($laResult as $laSingleResult) {
if($laSingleResult['diff'] == $min_diff) {
echo $laSingleResult['origin'] .PHP_EOL;
}
}

Related

How to get the nearest expiration date,

I have this array string :
[
{"expiration": "0000-00", "quantity": -50},
{"expiration": "2023-02", "quantity": 100},
{"expiration": "2022-03", "quantity": 50}
]
how to get the nearest expiration date, means here I need to get the third one 2022-03 and ignore others & also ignore the date that comes with 0000-00
my code:
$minDate = "";
foreach (json_decode($row['items']) as $item) {
if ($item->expiration != "0000-00") {
$minDate = min($item->expiration);
}
}
dd($minDate);
You can try something like this: -
$arr = getNearestExp($row['items']);
print_r($arr);
/**
*To get the Nearest Expiration date
*#input json array of expiration & quantity as
*per the question
*/
function getNearestExp($items){
$items = json_decode($items); // convert the items to json object
$itemArr = [];
foreach($items as $item) {
// exclude the '0000-00' expiration
if($item->expiration != '0000-00'){
$itemArr[strtotime($item->expiration)] = (array)$item;
}
}
// sort the out put array to ASC order to get the smallest value 1st
ksort($itemArr);
// Re indexing the array to proper index keys
$itemArr= array_values($itemArr);
// return the first value of the array
return $itemArr[0];
}
min(), require two values (or more) and return the lowest value. In your case you gave only one. Then, min() cannot compare strings.
You can use several arrays functions such as array_column(), array_filter(), sort() and reset() (Less verbose, but could be less efficient with large data) to achieve this :
$data = json_decode('[
{"expiration": "0000-00", "quantity": -50},
{"expiration": "2023-02", "quantity": 100},
{"expiration": "2022-03", "quantity": 50}
]');
// extract 'expiration', remove '0000-00'
$data = array_filter(array_column($data, 'expiration'), fn($item) => $item != '0000-00');
sort($data);
var_dump(reset($data)); // string(7) "2022-03"
demo (3v4l.org)
Here is another way.
<?php
//Enter your code here, enjoy!
$json = "[{\"expiration\": \"0000-00\", \"quantity\": -50},{\"expiration\": \"2023-02\", \"quantity\": 100},{\"expiration\": \"2022-03\", \"quantity\": 50}]";
$array = json_decode($json);
$currentDate = date_create_from_format('Y-m-d', date("Y-m-d"));
$daysDiff = 365;
$nearest = "";
for($i = 0; $i<count($array); $i ++) {
$v = $array[$i];
$d = explode("-",$v->expiration);
if(checkdate(intval($d[1]),1,intval($d[0]))) {
$date =date_create_from_format('Y-m-d',$d[0]."-".$d[1]."-1");
$dateDiff = (array)date_diff($currentDate, $date);
if($dateDiff["days"] < $daysDiff ) {
$daysDiff = $dateDiff["days"];
$nearest = $v;
}
}
}
var_dump($nearest)
?>
Bit more low key (it's been a while since I've done php)

how I should compare my data to an array json

I'm having a hard time in comparing day to array
this is my array:
array:2 [
0 => {
"id": 1
"time_in": "08:00:00"
"time_out": "17:00:00"
"days": "["tuesday","thursday","saturday"]"
}
1 => {
"id": 2
"time_in": "09:00:00"
"time_out": "18:00:00"
"days": "["monday","wednesday","friday"]"
}
]
note: days are json data from database
and I have this variable day
$day = 'friday';
I just want to get the array data with 'friday' in their days
please help me on my code I just don't know how I should manipulate it
or what code I will use to get it
I expect to have this output:
$day = 'friday';
1 => {
"id": 2
"time_in": "09:00:00"
"time_out": "18:00:00"
"days": "["monday","wednesday","friday"]"
}
because it has friday in its day
you can use in_array() function, which searches an array for a specific value.
for search $day="friday", i declare another array as $b and put filtering value into it.
Try this:
$array = array(array("id"=>"1","time_in"=>"08:00:00","time_out"=>"17:00:00","days"=>'["tuesday","thursday","saturday"]'),
array("id"=>"2","time_in"=>"09:00:00","time_out"=>"18:00:00","days"=>'["monday","wednesday","friday"]'));
$day = "friday";
$b = array();
foreach ($array as $val) {
if (in_array($day,$val['days'])) {
$b[] = $val;
}
}
print_r($b);
let's say that your JSON data is defined as $json:
$json_array = json_decode($json);
$result = [];
foreach($json_array as $arr){
if(in_array($day,$arr->days)){
$result[] = $arr;
}
}
use in_array to find data in array
foreach($your_array as $obj){
if(in_array($day, $obj->days)){
return $obj;
}
}
<?php
// the day you want
$day = 'friday';
// decode json to php array
$days = json_decode($yourJSONArrayFromDatabase, true);
for ($i=0; $i < count($days); $i++)
{
if (in_array($day, $days[$i]['days'])) {
echo json_encode($days[$i]);
break;
}
}

How to loop through an JSON array getting unique values [PHP]

I am trying to loop through a JSON Array returning a unique date and all the tasks associated with that date.
This is an example of my JSON array:
<!-- language: lang-json -->
[
{
"task":"Clean my teeth",
"date":"today"
},
{
"task":"Jumping Jacks",
"date":"tomorrow"
},
{
"task":"Call Mom",
"date":"today"
},
{
"task":"Wash The Dog",
"date":"2017/03/01"
},
{
"task":"Clean The House",
"date":"today"
}
]
I want to display something like this:
Today
Clean my teeth
Call Mom
Tomorrow
Jumping Jacks
2017/03/01
Clean The House
Here is my function: I can get all the unique days but I'm not sure how to display the tasks associated with that day.
public static function Iteration()
{
$file = file_get_contents("newfile.php");
$result = rtrim( $file, ",");
$array = json_decode('[' . $result . ']');
$unique_dates = array();
$unique_tasks = array();
foreach($array as $item) {
if ( in_array($item->date, $unique_dates) ) {
continue;
}
$unique_dates[] = $item->date;
$time = strtotime($item->date);
$newformat = date('Y-m-d',$time);
echo '<h2>' . $newformat . '</h2>';
echo $item->task;
}
}
You can traverse the JSON list, and keep the unique records and store tasks at the same traversal.
By using the isset(), you can determine whether the key is unique or not.
Try this:
<?php
$json = '[{"task": "Clean my teeth","date": "today"},{"task": "Jumping Jacks","date": "tomorrow"},{"task": "Call Mom","date": "today"},{"task": "Wash The Dog","date": "2017/03/01"},{"task": "Clean The House","date": "today"}]';
$array = json_decode($json);
$res = array();
foreach ($array as $each) {
if (isset($res[$each->date]))
array_push($res[$each->date], $each->task);
else
$res[$each->date] = array($each->task);
}
foreach ($res as $date => $tasks){
echo "<h3>{$date}</h3>";
foreach ($tasks as $task)
echo "<p>$task</p>";
}

calculate avg return "0" PHP

I have MySQL with Float Values which are pressure parametters. I need to calculate average. But the code I make returns me average "empty" in my json response.
Here is the json response I get:
{"result":{"pressure":{"min":[{"Id":"2","presion":"0","Insertado":"2016-08-16 16:20:08"},{"Id":"5","presion":"0","Insertado":"2016-08-16 18:09:04"}],"max":[{"Id":"3","presion":"55","Insertado":"2016-08-16 16:22:14"}],"avg":[]},"last_entry":{"Id":"8","presion":"50","Insertado":"2016-08-16 18:28:45"}}}
As it shows. avg give empty!.
This is code in PHP
$press_values = get_press_values($json_object->result);
// get pressure result set with respected values
$press_result = get_press_result_set_from_values($json_object->result,$press_values);
// get latest entry
$latest_entry = get_latest_date_entry($json_object->result);
// Wrap results in an array
$output_result = array(
'pressure' => $press_result,
'last_entry' => $latest_entry
);
}
Then.
function get_press_values($result){
$min = -1;
$max = -1;
$avg = -1;
// get all pressure values
$pressures = array_map(function($result_item) {
return intval($result_item->presion);
}, $result);
if($pressures){
$min = min($pressures);
$max = max($pressures);
$avg = intval(calculate_average($pressures));
}
return array(
'min' => $min,
'max' => $max,
'avg' => $avg
);
}
Then:
function get_press_result_set_from_values($array,$value){
$min_objs = array();
$max_objs = array();
$avg_objs = array();
foreach ($array as $item) {
if($item->presion == $value['min']){
$min_objs[] = $item;
}
if($item->presion == $value['max']){
$max_objs[] = $item;
}
if($item->presion == $value['avg']){
$avg_objs[] = $item;
}
}
return array(
'min' => $min_objs,
'max' => $max_objs,
'avg' => $avg_objs,
);
}
then:
function calculate_average($arr) {
$total = 0;
$count = count($arr); //total numbers in array
foreach ($arr as $value) {
$total = $total + $value; // total value of array numbers
}
$average = ($total/$count); // get average value
return $average;
}
This part in your code:
if($item->presion == $value['avg']){
$avg_objs[] = $item;
}
will only add an item if the presion perfectly matches the average, which can be very unlikely, depending on your data of course.
update: For example you have the values 50, 51, 54, 55. The average is 53. Your code will not find any $item->presion which is equal to 53, because the average doesn't need an item that has that value (in contrast to min and max).
You should check if you actually mean the median (which has to be determined in a different way ...).
update2: to get the average into your result, you have to change
$avg_objs = array(); to $avg_objs = $value['avg'];. and remove the part from your code that I posted above.
Also, if you want your average to not be an integer, you should change the line
$average = ($total/$count);
to
$average = (float)$total / $count;
and remove the intval from:
$avg = intval(calculate_average($pressures));

return indexes of the max values in an associative array in php [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Return index of highest value in an array
How can i return all the index of the max value.. for example a have this array that contains grades of students
$grade = array(
"anna" => "5",
"lala"=>"7",
"eni"=>"7",
i want to return the names of the student who have the max grade
in this case should print: lala
eni
You can use max() in order to find the higest value and then do array_keys() over it.
http://php.net/manual/en/function.max.php
http://php.net/manual/en/function.array-keys.php
E.g.
$grade = array(
"anna" => "5",
"lala"=>"7",
"eni"=>"7",
$max = max($grade); // $max == 7
array_keys($grade, $max);
it looks like a school exercise ...
Ok, you can write something like that:
$maxInd = -1;
foreach($grade as $name => $ind) {
if($ind > $maxInd) {
$maxInd = $ind;
$maxRes = array();
}
if($ind == $maxInd) {
$maxRes[] = $name;
}
}
return "The highest names are " . implode(', ',$maxRes);
please, let me know if it works!
you can do sth. like this:
$inversed = Array();
$highGrade = 0;
foreach ($grade AS $student=>$grade){
if (isset($inversed[$grade]))
$inversed[$grade][] = $student;
else
$inversed[$grade] = Array($student);
if ($grade > $highGrade) $highGrade = $grade;
}
print_r($inversed[$highGrade]);
<?php
$grade = array(
"atest" => 6,
"banna" => "5",
"lala"=>"7",
"eni"=>"7");
asort($grade);
$reverse = array_reverse($grade);
$prev_val='';
$counter = 0;
foreach($reverse as $key=>$value)
{
if((($counter==1)&&($value==$prev_val))||($counter==0))
{
echo $key."->".$value."<br/>";
$prev_val = $value;
$counter++;
}
}
?>
I have added one more element to the array to clear your doubt.

Categories