grepped列表上的Perl标量运算符给出的值更少

时间:2014-09-11 10:38:06

标签: perl

我正在解决一个项目euler问题problem 19,该问题要求从01-01-1901到31-12-2000这个星期几作为第一天的月数。我了解了DateTime模块以获取日期的day_name()。我写了一行grep来做它

perl -MDateTime -E '
        say scalar grep {
            my $d = $_;
            grep {
                if ( DateTime->new( year => "$d", month => "$_", day => "1" )->day_name() =~ /monday/i ) {
                    say "$_ : $d";
                }
            } ( 1 .. 12 )
        } ( 1901 .. 2000 );
    '

它给出100作为答案,但它打印172行。我还尝试将say "$_ : $d";替换为(1),但仍显示为100.此外,对于1901年至1903年的6天,它显示为3。我试过MO = Deparse但是没有看错。所以我不得不将它与wc耦合以获得输出。

perl -E 'say scalar grep { $_ % 2 == 0 } (1..100)' 

output : 

50

为什么我的grep给了我不正确的值?

2 个答案:

答案 0 :(得分:1)

您在内部grep中打印,但返回多年来迭代的外部grep的scalar。有100个匹配年份,所以答案是正确的。

要使用您的想法,您必须迭代日期(年份和月份合计)并计算匹配。为此,您可以使用map

use Time::Piece;
say scalar grep 'Monday' eq 'Time::Piece'->strptime("$_ 1", '%Y %m %d')->fullday,
           map {
               my $y = $_;
               map "$y $_", 1 .. 12
           } 1901 .. 2000;

答案 1 :(得分:1)

您正在混淆mapgrep的目的。

如果要转换列表,请使用前者;如果要对列表进行过滤,请使用后者。

以下是您的脚本的修复:

$ perl -MDateTime -E '
    say scalar grep { $_->day_name() =~ /monday/i }
        map {
            my $y = $_;
            map DateTime->new( year => $y, month => $_, day => 1 ), ( 1 .. 12 )
        } ( 1901 .. 2000 );
    '
172