将数组匹配到引用数组中的值 - Perl

时间:2012-06-12 20:37:11

标签: arrays perl date reference dereference

我有以下数组引用数组:

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']];

2012年,IRS认可哪些法定假日。我想将数组@dueDate与该数组中的值匹配,如果存在,则返回1或true。

    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]);
        }
    }

我目前的尝试是什么 - while语句的条件永远不会成立。我尝试了几种不同的引用和解引用假期组合,但没有用。

在while语句中操作评估的最佳方法是什么,以便当@dueDate包含上面数组中的日期时块执行。

注意:@dueDate是Date :: Calc标准数组 - (年,月,日)

4 个答案:

答案 0 :(得分:3)

这应该会让你走上正轨。我在你的代码中看到的两个问题 - 一个数组数组应该在外部部分有正常的括号,并使用~~运算符来比较数组的相等性。

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!!";
    }
}

答案 1 :(得分:2)

首先,

my @holidays = [[2012,'01','02'],...,[2012,'12','25']];

应该是

my @holidays = ([2012,'01','02'],...,[2012,'12','25']);

您正在创建一个包含单个元素的数组。


实现你想要的最好的方法可能是使用哈希。

my %holidays = map { join('-', @$_) => 1 } @holidays;

然后您需要的只是

while ($holidays{join('-', @dueDate)}) {
   my $dow = Day_of_Week(@dueDate);
   @dueDate = Add_Delta_Days(@dueDate,
      $dow == 5 || $dow == 6 ? 8 - $dow : 1);
}

答案 2 :(得分:2)

这是我的答案,在Perl 5.14上工作,我也使用smartmatching ~~运算符来比较两个数组。

您分配给数组@holidays = [[2012,'01','02'],];实际上你将匿名数组[['2012','01','02']]分配给@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";
    }
}

答案 3 :(得分:0)

好的,有些事情:

1:列表包含在括号中,文字数组引用写在括号之间。所以,你应该:

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:当您查看$holidays[@dueDate]时,您正在调用标量上下文中的所有内容。特别是,由于@dueDate有三个元素,因此您只需查看$holidays[3]

3:除非您正在编写一段一次性代码,否则总是 use strict;use warnings;

所以,你想要这样的东西:

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);

上面的代码产生以下输出:

2012-01-02