Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

The code below includes two sets of arrays from which is found an intersection. Since all the dates in one appear within the other it's fairly easy to see that the intersection is ok.

However on printing out a conversion of the dates using Date::Calc there are more dates than in the intersection. I wonder what I am doing wrong??

#!/usr/bin/perl -w use strict; use CGI ':standard'; use Date::Calc qw(:all); #definitions: #========= print "Content-type: text/html\n\n"; my @calendar = qw~732235 732236 732237 732238 732239 732240 732312 7 +32313 732314 732315 732316 732317 732318 732319 732320 732321 732322 +732323 732324 732325 732326 732327 732328 732329 732330 732331 732332 + 732333 732334 732335 732336 732337 732338 732339 732340 732341 73234 +2 732343 732344 732345 732346 732347 732348 732349 732350 732351 7323 +52 732353 732354 732355 732356 732357 732358 732359 732360 732361 732 +362 732363 732364 732365 732366 732367 732368 732369 732370 732371 73 +2372 732373 732374 732375 732376 732377 732378 732379 732380 732381 7 +32382 732383 732384 732385 732386 732387 732388 732389 732390 732391 +732392 732393 732394 732395 732396 732397 732398 732399 732400 732401 + 732407 732408 732409 732410 732411 732412 732413 732414 732415 73241 +6 732417 732418 732419 732422 732423 732424 732425 732426 732427 7324 +28 732429 732430 732431 732432 732433 732434 732435 732491 732492 732 +493 732494 732495 732496 732497 732498 732499 732500 732501 732502 73 +2503 732504~; my @Calendararray = qw~732357 732358 732359 732360 732361 732362 73236 +3 732364 732365 732366 732367 732368 732369 732370 732371 732372 7323 +73 732374 732375 732376 732377~; my $e; my (@union, @intersect); my (%union, %intersect); my $count = 0; foreach my $e (@calendar) { $union{$e} = 1 } foreach $e (@Calendararray) { if ($union{$e}) { $intersect{$e} = 1 } $union{$e} = 1; } @intersect = keys %intersect; @union = keys %union; $count = @intersect; my %dates; my @alldays; my @alldays1; for ( @intersect ) { my ( $year, $month, $day ) = Add_Delta_Days( 1, 1, 1, $_ - 1 ); push @{ $dates{$year}->{$month} }, $day; } @calendar = sort @calendar; @Calendararray = sort @Calendararray; @intersect = sort @intersect; print "@calendar"; print "<br><br>"; print "@Calendararray"; print "<br><br>"; print "@intersect"; print "<br><br>"; my @linetoprint; my $statement; for my $year (sort keys %dates) { for my $month (sort keys %{$dates{$year}}) { @alldays = @{$dates{$year}{$month}}; my @months = qw (January February March April May June July August + September October November December); my $m_w = $months[$month -1]; foreach my $item (@alldays) { $item = sprintf ('%02d', $item); push (@alldays1, $item); } @alldays1 = sort (@alldays1); $statement = "$year: $m_w,&nbsp;&nbsp;@alldays1"; push (@linetoprint, $statement); } } $statement = join "<br>\n", @linetoprint; print "$statement";

Replies are listed 'Best First'.
Re: intersection of lists of dates produces too many results!!
by pg (Canon) on Oct 19, 2005 at 03:41 UTC

    If I have understood your question/problem correctly, then what you need is to reset @alldays1 each time (for each month), otherwise when it comes to march, the array contains days not just for Mar., but for both Mar. and Feb. (Could you please break your two long lines, so it fits the page without horizontal scroll bar ;-)

    @alldays1 = ();

    Just add this one line (the 20ish line from the bottom):

    use strict; use CGI ':standard'; use Date::Calc qw(:all); use Data::Dumper; print "Content-type: text/html\n\n"; my @calendar = qw~732235 732236 732237 732238 732239 732240 732312 732 +313 732314 732315 732316 732317 732318 732319 732320 732321 732322 732323 732324 732325 732326 732327 +732328 732329 732330 732331 732332 732333 732334 732335 732336 732337 732338 +732339 732340 732341 732342 732343 732344 732345 732346 732347 732348 732349 +732350 732351 732352 732353 732354 732355 732356 732357 732358 732359 732360 +732361 732362 732363 732364 732365 732366 732367 732368 732369 732370 732371 +732372 732373 732374 732375 732376 732377 732378 732379 732380 732381 732382 +732383 732384 732385 732386 732387 732388 732389 732390 732391 732392 732393 +732394 732395 732396 732397 732398 732399 732400 732401 732407 732408 732409 +732410 732411 732412 732413 732414 732415 732416 732417 732418 732419 732422 +732423 732424 732425 732426 732427 732428 732429 732430 732431 732432 732433 +732434 732435 732491 732492 732493 732494 732495 732496 732497 732498 732499 +732500 732501 732502 732503 732504~; my @Calendararray = qw~732357 732358 732359 732360 732361 732362 73236 +3 732364 732365 732366 732367 732368 732369 732370 732371 732372 732373 732374 +732375 732376 732377~; my $e; my (@union, @intersect); my (%union, %intersect); my $count = 0; foreach my $e (@calendar) { $union{$e} = 1 } foreach $e (@Calendararray) { if ($union{$e}) { $intersect{$e} = 1 } $union{$e} = 1; } @intersect = keys %intersect; @union = keys %union; $count = @intersect; print "count = $count\n"; my %dates; my @alldays; my @alldays1; for ( @intersect ) { my ( $year, $month, $day ) = Add_Delta_Days( 1, 1, 1, $_ - 1 ); push @{ $dates{$year}->{$month} }, $day; } @calendar = sort @calendar; @Calendararray = sort @Calendararray; @intersect = sort @intersect; print "@calendar"; print "<br><br>"; print "@Calendararray"; print "<br><br>"; print "@intersect"; print "<br><br>"; my @linetoprint; my $statement; for my $year (sort keys %dates) { for my $month (sort keys %{$dates{$year}}) { @alldays = @{$dates{$year}{$month}}; @alldays1 = (); print "all days = ", join(",", @alldays), "\n"; my @months = qw (January February March April May June July August + September October November December); my $m_w = $months[$month -1]; foreach my $item (@alldays) { $item = sprintf ('%02d', $item); push (@alldays1, $item); } @alldays1 = sort (@alldays1); $statement = "$year: $m_w,&nbsp;&nbsp;@alldays1"; push (@linetoprint, $statement); } } $statement = join "<br>\n", @linetoprint; print "$statement";

    The print out now looks like:

    2006: February,&nbsp;&nbsp;15 16 17 18 19 20 21 22 23 24 25 26 27 28<b +r> 2006: March,&nbsp;&nbsp;01 02 03 04 05 06 07
      Of course! Tis either the lateness of the hour, or the earliness of the hour!!.

      Many thanks

Re: intersection of lists of dates produces too many results!!
by GrandFather (Saint) on Oct 19, 2005 at 03:56 UTC

    As a matter of style: declare variables in as small a scope as possible. In this case you wouldn't have had a problem if you had declared @alldays and @alldays1 within the loop. You could choose a better name for @alldays1 too: @alldaysFmt whould show intent more.


    Perl is Huffman encoded by design.

      OTOH: my @months = qw (January February March April May June July August September October November December); is better located in a broader scope, i.e. outside the $year-loop.


      s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
      +.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e

        Agreed. If one were nit picking one could point out that that is a constant and should perhaps be at global scope.


        Perl is Huffman encoded by design.
Re: intersection of lists of dates produces too many results!!
by Skeeve (Parson) on Oct 19, 2005 at 06:50 UTC

    I see a completely unrelated problem with your code:

    foreach my $e (@calendar) { $union{$e} = 1 } foreach $e (@Calendararray) { if ($union{$e}) { $intersect{$e} = 1 } $union{$e} = 1; } @intersect = keys %intersect; @union = keys %union;
    What will happen when you have these values (no real values, just to show you what I mean)
    @calendar= qw~ 1 ~; @Calendararray=qw~ 2 2 ~;
    You will end up with an @intersection containing "2".


    s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
    +.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e