Development PHP: search array for closest key

Discussion in 'Software' started by jezmck, 1 Aug 2006.

  1. jezmck

    jezmck Minimodder

    Joined:
    25 Sep 2003
    Posts:
    4,456
    Likes Received:
    36
    I have an array like the following:
    PHP:
    Array ( 
    [
    '2006-07-01'] => 15.80
    ['2006-09-01'] => 18.09 
    ...
    [
    '2006-12-01'] => 11.22 )
    The index/key is of course a date, and I want to search forwards and back.

    For example, I want to (dynamically)
    look for the value at 2006-08-01, not find it,
    look for 2006-07-31, not find it,
    etc until I find the value at 2006-07-01, and use that for further calculations.

    I realise that I could use
    PHP:
    $arr[date('Y-m-d'strtotime($date.' -1 day'))]
    to search but I hope there is an easier way.

    All suggestions welcome. :)
     
  2. eek

    eek CAMRA ***.

    Joined:
    23 Jan 2002
    Posts:
    1,600
    Likes Received:
    14
    That's probably the most elegant way.

    If you wanted to avoid using the date function though you could just have three vars corresponding to year, month and day which you just change one each iteration. Obviously you would need to do a check when to change the year and month, and also when to reset the day to 1 or 31 due to varying length of each month. Once you have done this you can just concatenate them $year."-".$month."-".$day before using array_key_exists to check if it exists.

    Very rougthly you could have:
    PHP:
    <?php

    $arr 
    = array (
    '1989-08-01' => 15.80 ) ;

    $found true;

    $ts time();
    $date date('Y-m-d'$ts);
    while (!
    array_key_exists($date$arr)) {
        
    $ts strtotime('-1 day',$ts);
        
    $date date('Y-m-d'$ts);
        if (
    substr($date,0,4) == 1990) {
            
    $found false;
            break;
        }
    }
    if (
    $found)
        echo 
    $date." => ".$arr[$date];
    else
        echo 
    "date not found";

    ?>
    It's functional, but I would consider tidying it up and putting stuff into functions... this would also allow you to add a flag so whether you add/remove a day depending on which way you want to traverse it.
     
  3. jezmck

    jezmck Minimodder

    Joined:
    25 Sep 2003
    Posts:
    4,456
    Likes Received:
    36
    I like the
    PHP:
    while (!array_key_exists($date$arr)) { 
    bit, I would have tested the return value - I imagine your suggestion is quicker.

    Not so keen on the string manip though, there's too much risk of getting illegal dates.

    [OT] why 1989-08-01? you were 5 years and 2 months old. [/OT]

    Any further thoughts/suggestions welcome.
     
  4. simon w

    simon w What's a Dremel?

    Joined:
    3 Nov 2003
    Posts:
    1,302
    Likes Received:
    0
    Your array indexes are strings, how can you avoid string manipulation altogether?
     
  5. eek

    eek CAMRA ***.

    Joined:
    23 Jan 2002
    Posts:
    1,600
    Likes Received:
    14
    Maybe, maybe not. It probably depends how the algorithm works - it may even test the return value. The thing is though it's always a safer bet to stick with built-in functions like this than start getting involved with non-existent and null values which are prone to causing bugs![/quote]
    Indeed I was!! Strange coincedence it worked out like that really, I was only using 1989 to test if the 'date not found' thing worked because as you can see I used 1990 as the cut off date (don't want to get stuck in an infinite loop now hehe).
    Yeah as I mentioned above, it would be a lot neater to stick it all in a couple of functions. Even better would be to create an object however if you're not using PHP5 then you are going to be missing out on most of the benefits that come with OO so may not be worthwhile :)
     
  6. jezmck

    jezmck Minimodder

    Joined:
    25 Sep 2003
    Posts:
    4,456
    Likes Received:
    36
    I was refering to the danger of 'manual' string manipulation, rather than using the built in functions.

    absolutely true, I just hadn't considered any other options.

    I could go OO if I wanted, but I don't think there are any benefits in this instance.
     
  7. simon w

    simon w What's a Dremel?

    Joined:
    3 Nov 2003
    Posts:
    1,302
    Likes Received:
    0
    If the array comes from a database you could create a table of dates and left join from it onto your current table(s). This would give you NULL values for the dates where no value exists.

    You would of course have to maintain the date table, although this could be automated.
     
  8. jezmck

    jezmck Minimodder

    Joined:
    25 Sep 2003
    Posts:
    4,456
    Likes Received:
    36
    ta.

    I am now doing the overall process another way (and the array-search is replaced with a DB search instead).
     
    Last edited: 3 Aug 2006
  9. Hwulex

    Hwulex What's a Dremel?

    Joined:
    1 Feb 2002
    Posts:
    4,007
    Likes Received:
    1
    Just a note to say how slow array_key_exists is. Granted it does offer you that extra functionality of returning true if [key]=>null whereas isset() and if ($array[key]) do not, but that's not always necessary.

    Just thought I'd point that out. :)
     

Share This Page