Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

How to iterate thru entire array with start point other than beginning

by dirtdog (Monk)
on Sep 01, 2016 at 16:33 UTC ( [id://1170987]=perlquestion: print w/replies, xml ) Need Help??

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

Hi Monks,

I have a requirement to provide stats on the last 12 months from current day. I have an array of months so I would need to report out Oct 15', Nov 15', Dec 15', Jan 16' thru Sep 16' as the last column. Next month, the report would run on Oct, 1st and so the report would begin with Nov 15', Dec 15', Jan 16', etc...

My code is as follows

#!/usr/bin/perl use POSIX 'strftime'; use strict; my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime; my $curr_mth = sprintf "%2d", strftime('%m', $sec,$min,$hour,$mday,$mo +n,$year,$wday,$yday,$isdst); my @month_name = qw(January February March April May June July August +September October November December); while (<DATA>) { my %by_month = split ' ', $_; for my $m ( $curr_mth .. $#month_name) { if ( exists ( $by_month{$month_name[$m]} ) ) { print "$by_month{$month_name[$m]} EXISTS for $ +month_name[$m] Row $.\n"; } else { print "$by_month{$month_name[$m]} DOES NOT EXI +STS $month_name[$m] for row $.\n"; } } } __DATA__ February 1 March 5 July 4 August 5 October 7 January 3 March 4 April 6 May 5 June 7 July 8 August 10 September 4 Oc +tober 9 November 11 December 8 March 2 June 3 August 1 December 7

I have figured out how to start looping thru the Months array at October, but I can't figure out how to go past the end to September.

thanks very much for your time and effort and ideas.

Replies are listed 'Best First'.
Re: How to iterate thru entire array with start point other than beginning
by choroba (Cardinal) on Sep 01, 2016 at 16:53 UTC
    I don't understand your code. But to create "rotating" arrays, you can use the % operator - the modulo.
    #!/usr/bin/perl use warnings; use strict; my @month_names = qw( January February March April May June July August September October November December ); for my $start (0 .. 11) { for my $month ($start .. 11 + $start) { print $month_names[ $month % 12 ], ' '; } print "\n"; }
    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,

      thank you! This will work perfectly.

Re: How to iterate thru entire array with start point other than beginning
by stevieb (Canon) on Sep 01, 2016 at 17:22 UTC

    Yet another way using DateTime. I threw in the cumulative month results for something to do:

    use warnings; use strict; use DateTime; my $dt = DateTime->now; my %report; while (<DATA>) { chomp; my %month_data = split; for (keys %month_data){ $report{$_} += $month_data{$_}; } } my $report_months = 11; while ($report_months > -1){ my $now = $dt->clone; my $past_month = $now->subtract(months => $report_months)->month_name; print exists $report{$past_month} ? "$past_month: $report{$past_month}\n" : "$past_month: no data available\n"; $report_months--; } __DATA__ March 5 July 4 August 5 October 7 January 3 March 4 April 6 May 5 June 7 July 8 August 10 September 4 October 9 November 11 December 8 March 2 June 3 August 1 December 7

    Output:

    October: 16 November: 11 December: 15 January: 3 February: no data available March: 11 April: 6 May: 5 June: 10 July: 12 August: 16 September: 4
Re: How to iterate thru entire array with start point other than beginning
by GrandFather (Saint) on Sep 02, 2016 at 01:53 UTC

    Slices are fun:

    use strict; use warnings; my @month_name = qw( January February March April May June July August September October November December ); for my $startMonthIdx (0 .. 11) { my @sel = @month_name[$startMonthIdx .. 11, 0 .. $startMonthIdx - +1]; print "$startMonthIdx: @sel\n"; }

    Prints:

    0: January February March April May June July August September October + November December 1: February March April May June July August September October Novembe +r December January 2: March April May June July August September October November Decembe +r January February 3: April May June July August September October November December Janu +ary February March 4: May June July August September October November December January Fe +bruary March April 5: June July August September October November December January Februa +ry March April May 6: July August September October November December January February Ma +rch April May June 7: August September October November December January February March A +pril May June July 8: September October November December January February March April Ma +y June July August 9: October November December January February March April May June Jul +y August September 10: November December January February March April May June July Augus +t September October 11: December January February March April May June July August Septemb +er October November
    Premature optimization is the root of all job security
      no need to concatenate two ranges. Instead of
      my @sel = @month_name[$startMonthIdx .. 11, 0 .. $startMonthIdx - +1];
      you can use
      my @sel = @month_name[$startMonthIdx - 12 .. $startMonthIdx - 1];
      gives the same output as above.

      The only objection I would make to the array slice approaches of GrandFather here or soonix here (++ to both by the way) is that they start to produce strange results for  $startMonthIdx values outside the  0 .. @month_name range. This may not be a real problem since one may never endeavor to venture outside this range.

      The attraction for me of the modulo-@month_name approach is that it gives sensible results for any weird positive or negative range whatever. I would prefer to impose any range limits in a separate step and then just reliably handle whatever range emerged from the validation process.

      c:\@Work\Perl\monks>perl -wMstrict -le "my @months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec); ;; for my $offset (-25 .. -11) { printf 'offset %3d: ', $offset; my @sel = map $months[ ($_ + $offset) % @months ], -109 .. -95; printf qq{@sel}; print ''; } " offset -25: Nov Dec Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec Ja +n offset -24: Dec Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec Jan Fe +b offset -23: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec Jan Feb Ma +r offset -22: Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec Jan Feb Mar Ap +r offset -21: Mar Apr May Jun Jul Aug Sep Oct Nov Dec Jan Feb Mar Apr Ma +y offset -20: Apr May Jun Jul Aug Sep Oct Nov Dec Jan Feb Mar Apr May Ju +n offset -19: May Jun Jul Aug Sep Oct Nov Dec Jan Feb Mar Apr May Jun Ju +l offset -18: Jun Jul Aug Sep Oct Nov Dec Jan Feb Mar Apr May Jun Jul Au +g offset -17: Jul Aug Sep Oct Nov Dec Jan Feb Mar Apr May Jun Jul Aug Se +p offset -16: Aug Sep Oct Nov Dec Jan Feb Mar Apr May Jun Jul Aug Sep Oc +t offset -15: Sep Oct Nov Dec Jan Feb Mar Apr May Jun Jul Aug Sep Oct No +v offset -14: Oct Nov Dec Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov De +c offset -13: Nov Dec Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec Ja +n offset -12: Dec Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec Jan Fe +b offset -11: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec Jan Feb Ma +r


      Give a man a fish:  <%-{-{-{-<

Re: How to iterate thru entire array with start point other than beginning
by Anonymous Monk on Sep 01, 2016 at 16:50 UTC
    #!/usr/bin/perl -l # http://perlmonks.org/?node_id=1170987 use strict; use warnings; my @month_name = qw(January February March April May June July August +September October November December); for my $start (0 .. 11) { my @wanted = (@month_name, @month_name)[$start .. $start + 11]; print "@wanted"; }

      I spoke too soon. I'm actually a little stumped on the % modulo operator and the example. I see a lot more than 12 months being printed out. The goal is to start with current month +1 (so October if using today in the example) and then print the 12 months in order from there..

      #!/usr/bin/perl use POSIX 'strftime'; use strict; my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime; my $curr_mth = sprintf "%2d", strftime('%m', $sec,$min,$hour,$mday,$mo +n,$year,$wday,$yday,$isdst); my @month_name = qw(January February March April May June July August +September October November December); for my $m ( 0 .. $#month_name) { print "Month name is: $month_name[$m]\n"; }

      I'm trying to get out as follows:

      Month name is: October Month name is: November Month name is: December Month name is: January Month name is: February Month name is: March Month name is: April Month name is: May Month name is: June Month name is: July Month name is: August Month name is: September

      then next month the output would be:

      Month name is: November Month name is: December Month name is: January Month name is: February Month name is: March Month name is: April Month name is: May Month name is: June Month name is: July Month name is: August Month name is: September Month name is: October

        If you want to use the % operator, it can be quite simple. To expand on the GP anonymonk's script:

        #!/usr/bin/env perl use strict; use warnings; # Set an array of names my @names = qw/January February March April May June July August September October November December/; # Find the index number of next month my $next = (localtime)[4] + 1; # Loop over the next 12 months and print the month names in sequence for my $monpos ($next .. $next + 11) { print "Month is $names[$monpos % 12]\n"; }

        Please ask if anything in this piece of code is unclear.

        I have some code that works, but boy o' boy is it ugly.

        #!/usr/bin/perl use POSIX 'strftime'; use strict; my $m; my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime; my $curr_mth = sprintf "%2d", strftime('%m', $sec,$min,$hour,$mday,$mo +n,$year,$wday,$yday,$isdst); my @month_name = qw(January February March April May June July August +September October November December); for ( $curr_mth .. $#month_name) { print "Month name is: $month_name[$_]\n"; $m++; } if ( $m < 12 ) { for my $n ( 0 .. ($#month_name - $m) ) { print "Month name is: $month_name[$n]\n"; } }

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1170987]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (5)
As of 2024-03-28 13:29 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found