Reputation: 329
I have the following array of references to arrays:
my @holidays = [[2012,'01','02'],[2012,'01','16'],[2012,'02','20'],[2012,'04','16'],[2012,'05','28'],[2012,'07','04'],[2012,'09','03'],[2012,'10','08'],[2012,'11','12'],[2012,'11','22'],[2012,'12','25']];
Which are IRS recognized legal holidays during 2012. I would like to match the array @dueDate to a value in that array and return 1 or true if it is present.
while ($holidays[@dueDate]){
print ("Found Holiday \t join('-',@dueDate)");
@dueDate = Add_Delta_Days(@dueDate, 1);
if ( Day_of_Week(@dueDate) > 5){
@dueDate = Monday_of_Week((Week_Number(@dueDate)+1), $dueDate[0]);
}
}
Is my current attempt at this - the condition of the while statement is never true. I've tried a few different combinations of referencing and dereferencing holidays to no avail.
What would the best way be to manipulate the evaluation within the while statement such that the block executes when @dueDate contains a date within my array above.
Note: @dueDate is a Date::Calc standard array - (Year, Month, Day)
Upvotes: 4
Views: 183
Reputation: 6592
This should put you on the right track. Two problems I see with your code - an array of arrays should have normal parentheses on the outer part, and use the ~~ operator to compare arrays for equality.
my @holidays = ([2012,'01','02'],[2012,'01','16'],[2012,'02','20'],[2012,'04','16'],
[2012,'05','28'],[2012,'07','04'],[2012,'09','03'],[2012,'10','08'],[2012,'11','12'],
[2012,'11','22'],[2012,'12','25']);
my $i;
my @duedate = [2012, '01', '02'];
for ($i = 0; $i < @holidays; $i++)
{
if (@holidays[$i] ~~ @duedate)
{
print "matched!!";
}
}
Upvotes: 3
Reputation:
Okay, a few things:
1: Lists are contained in parentheses, and literal array references are written between brackets. So, you should have:
my @holidays = ([2012,'01','02'],[2012,'01','16'],[2012,'02','20'],[2012,'04','16'],[2012,'05','28'],
[2012,'07','04'],[2012,'09','03'],[2012,'10','08'],[2012,'11','12'],[2012,'11','22'],[2012,'12','25']);
2: When you look at $holidays[@dueDate]
, you're calling everything in scalar context. In particular, since @dueDate
has three elements, you're only looking at $holidays[3]
.
3: Unless you're writing a piece of throwaway code, always use strict;
and use warnings;
.
So, you want something like this:
use strict;
use warnings;
my @holidays = ([2012,'01','02'],[2012,'01','16'],[2012,'02','20'],[2012,'04','16'],[2012,'05','28'],
[2012,'07','04'],[2012,'09','03'],[2012,'10','08'],[2012,'11','12'],[2012,'11','22'],[2012,'12','25']);
my @dueDates=([2012,'01','01'],[2012,'01','02'],[2012,'01','03']); #Or whatever
my @due_dates_that_are_holidays=();
foreach my $due_date(@dueDates)
{
foreach my $holiday(@holidays)
{
my ($h_y,$h_m,$h_d)=@$holiday; #Capturing year month and day from the array reference
my ($d_y,$d_m,$d_d)=@$due_date; #Ditto for the due date
if($h_y == $d_y and $h_m eq $d_m and $h_d eq $d_d)
{
push @due_dates_that_are_holidays,$due_date;
}
}
}
print join("-",@{$_}) . "\n" foreach(@due_dates_that_are_holidays);
The above code produces the following output:
2012-01-02
Upvotes: 0
Reputation: 3465
This is my answer, working on Perl 5.14, also I use smartmatching ~~ operator to compare two arrays.
You assign to array @holidays = [[2012,'01','02'], ]; isn't correct actually you assign anonymous array [ ['2012', '01', '02'], ] to first element of @holidays.
use v5.14;
my @holidays = ( ['2012', '01', '02'], ['2012', '01', '16'] );
my @due_date = ( '2012', '01', '16' );
for my $holiday (@holidays) {
if (@$holiday ~~ @due_date) {
say "holiday match";
}
}
Upvotes: 2
Reputation: 385897
First,
my @holidays = [[2012,'01','02'],...,[2012,'12','25']];
should be
my @holidays = ([2012,'01','02'],...,[2012,'12','25']);
You're creating an array with a single element.
Probably the best way to achieve what you want is to use a hash.
my %holidays = map { join('-', @$_) => 1 } @holidays;
Then all you need is
while ($holidays{join('-', @dueDate)}) {
my $dow = Day_of_Week(@dueDate);
@dueDate = Add_Delta_Days(@dueDate,
$dow == 5 || $dow == 6 ? 8 - $dow : 1);
}
Upvotes: 2