in reply to Finding array element

Let's start off with the easy part, identifying the location of said element:
my $i = 0; foreach my $href ( @array ) { last if date_larger_than( $href->{ 'date' }, $today ); $i++ } # Mark it, if you want, assuming found... if ( $i < scalar @array ) { # $array[$i]->{ 'isnext' } = 1; }
That's the easy part. Now, you need to define date_larger_than, which I can think of several possibilities.

If you don't need the textual representation of the data; that is, if you can handle "20010201" as well as "2001-02-01", then you can simply use a numerical comparison, assuming that the hash's dates are changed to the numerical representation as well.

You can change them on the fly, as well:

my ($y, $m, $d) = ( $date =~ /(\d{4})-(\d{2})-(\d{2})/ ); $date_num = $y*10000 + $m*100 + $d;
And compare like that.

There's numerous date classes that could probably read that date in into an object, and then use their built in date comparators to see which date is greater.

In this case , for date comparisons, there is definitely MTOWTDI.

Update - Added grouping on the regex above, oops


Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain

Replies are listed 'Best First'.
Re: Re: Finding array element
by chromatic (Archbishop) on Mar 28, 2001 at 23:08 UTC
    There's no need for a regex here, and the math is doubly overkill. Let's use my favorite underrated function, the transliteration operator:
    my $date = "2001-03-28"; (my $d2 = $date) =~ tr/-//d;
Re: Re: Finding array element
by Vondikall (Initiate) on Mar 29, 2001 at 17:04 UTC
    If the date is in YYYY-MM-DD format, then a simple string comparison works fine
    my @dates = qw( 2001-12-24 1999-03-2 2004-04-23 ); print join(', ', sort { $b cmp $a } @dates );
    prints
    2004-04-23, 2001-12-24, 1999-03-2
    The whole thing is much simpler if you use grep. In fact, you can find, and set the 'isnext' key in a single line. What you want to find is the smallest date larger than or equal to the given date. First sort the dates in ascending order:
    sort { $a->{date} cmp $b->{date} } @$array
    then grep out those that are larger than the given date:
    grep { $_->{date} ge $today } ...
    and the first one of those will be your match:
    ( ... )[0]->{isnext} = 1;
    So the answer goes like this:
    (grep {$_->{date} ge $today} sort {$a->{date}cmp $b->{date} } @$array) +[0]->{isnext} = 1;
    The whole thing then looks like this:
    my $today = '2001-03-28'; my $array = [ { date => '2001-02-01' }, { date => '1999-04-09' }, { date => '2001-03-31' }, { date => '2001-03-24' }, { date => '2001-04-15' }, ]; # find the smallest date larger than or equal to today. # set the isnext flag (grep { $_->{date} ge $today } sort { $a->{date} cmp $b->{date} } @$a +rray)[0]->{isnext} = 1; # print all out and indicate which one is next... for my $e (@$array) { print "\n", $e->{date}; print " this is next" if $e->{isnext}; } # alternatively : my $thenext = (grep { $_->{date} ge $today } sort { $a->{date} cmp $b- +>{date} } @$array)[0]; print "\nThe next date is: $thenext->{date}\n";
Re: Re: Finding array element
by voyager (Friar) on Mar 28, 2001 at 23:05 UTC
    Thanks. I'm set now.

    FWIW I am using HTTP::Date::parse_date to get dates into a string format that is suitable for sorting.