0

I have an array of id's and unix times

$array =  Array(
         [12] => 14235183200,
         [8] => 1443045600,
         [1] => 1417388400
     );

and current time $curr_time = time();. I need to check which of these is the closest to the current time, and then to get the key of the array for that value which is the closest. If the time has passed, then of course that value shouldn't count (only future dates are important).

min() should give me lowest value of the compared values. But if I put current date, any future date is greater, and I get current date as a result. array_search() will give me key I needed. So I need this:

$key = array_search($array, $min_date);

where $min_date is the date closest to the current one from the array. But how to preform the check? I tried with foreach($array as $value), but when i tried

foreach($array as $value){

}

any test fails since $value is a string of all values combined.

2 Answers 2

1

We have 2 basic rules;

  • Anything lower than the time ($curr_time) is excluded
  • The closest one to time ($curr_time) is selected.

This means we can do 2 different bits of logic and get our answer;

  • Sort the array from least to most (sort it ASC)
  • If the time is less than $curr_time, exclude it
    • The first one that isn't less than $curr_time is our closest.

natsort($array); //Sort from lowest-highest
foreach($array as $k => $time) { //Loop through our array of times
   if( $time < $time_to_look_for ) { 
      continue; //It's less than the time we need, so exclude it
   } else {
      //First entry that isn't less than the time we need
      echo $k;
      break;
   }
}

https://eval.in/301601

Manual links;

Sign up to request clarification or add additional context in comments.

Comments

1

The array_search function is best if the value you are looking for is in the array. Because you are looking for the closest value, which may not be in the array, array_search will not work. However, this is rather simple to program. You need to go through every value - so you are correct in that you need foreach. You need to maintain the key of the best value you find, so you need a variable that I will call $key. The concept of "closest" has more than one definition. I will define it as the smallest result from abs($cur_time-$value). From there, your code is practically written for you:

Note: I changed this code because it was asked that times in the past be ignored. I did this with a continue statement, mainly just so this example now shows how to use a continue and a break in a foreach loop.

$key = null; // I initialize it this way. You can do it a different way.
foreach($array as $k=>$v)
{
    if($v<$cur_time) continue;
    if($key == null) $key = $k; // The first item is closest by default.
    elseif($v-$cur_time < $array[$key]-$cur_time)
        $key = $k;
    if($array[$key] == $cur_time) break;
}

When this ends, $key will have the key of the closest value to $cur_time.

I added a break based on the comment below. If you find the value, there is no point to continue searching.

5 Comments

You're doing some unnecessary looping. If your array is 1,000,000 (for arguments sake) big, and it's found on the first few iterations, then that's a whole bunch of iterations wasted. You should have a break; in here somewhere.
Correct. Once $v == $cur_time, a break will avoid continuing to loop. I could sort, but that introduces a new problem. My solution is O(n). If I sort first, I will guarantee a solution that is, at best, O(n log n).
This returned the date from 2014 :\ It is the closest one, but I don't need the past time. The code you posted, if you didn't break it, it would loop all the time?
As I mentioned, the definition of "closest" is vague. If you want to skip any value less then $cur_time, you can change the calculation of the time difference or add: if($v<$cur_time) continue; as the first line of the foreach block. As for the break - that is a shortcut. Will not loop forever and ever and ever. It loops through the array once and only once.
Thanks for the help, I managed to get it working with other code, but your explanation is also great.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.