Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

help formatting output of particular loop

by eisdrache (Novice)
on Jan 29, 2007 at 08:12 UTC ( #597036=perlquestion: print w/replies, xml ) Need Help??

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

first i query the database, this is the result
id_number start_date start_time CA642997 2007-01-29 03:05:00 CA651167 2007-01-29 03:05:00 CA651038 2007-01-29 19:00:00 CA650995 2007-01-30 19:00:00 CA652568 2007-01-31 01:05:00 CA652880 2007-01-31 01:30:00 CA652884 2007-01-31 06:00:00 CA643602 2007-02-01 00:30:00 CA652881 2007-02-01 01:00:00
i would like to print that out to a web page like this:
2007-01-29 CA642997 03:05:00 CA651167 03:05:00 CA651038 19:00:00 2007-01-30 CA650995 19:00:00 2007-01-31 CA652568 01:05:00 CA652880 01:30:00 CA652884 06:00:00 2007-02-01 CA643602 00:30:00 CA652881 01:00:00 etc...
i think you get the idea. but, i cannot figure out how to do this for some reason. i think i might have brain damage now from thinking too hard. this should be an easy problem, so if anyone can help, thanks in advance.

Replies are listed 'Best First'.
Re: help formatting output of particular loop
by friedo (Prior) on Jan 29, 2007 at 08:46 UTC

    It seems to me like you should make a hash of arrays mapping dates to their records. So, you could do something like this:

    my %records; while( my $row = $sth->fetchrow_hashref ) { push @{ $records{ $row->{start_date} } }, $row; }

    Then you can loop through that hash (sorting as necessary) to output the records. Since the outer hash is keyed by the datestamp, we can sort it easily:

    foreach my $date( sort keys %records ) { print $date, "\n"; # then get each record, sorted by the start time my @recs = sort { $a->{start_time} cmp $b->{start_time} } @{ $records{$date} }; foreach my $rec( @recs ) { print $rec->{id_number}, "\t", $rec->{start_time}; print "\n"; } }

    That's all untested but should get you on the right track.

Re: help formatting output of particular loop
by GrandFather (Saint) on Jan 29, 2007 at 09:29 UTC

    As a little workout for my newly acquired CGI muscles I put together:

    use strict; use warnings; use CGI::Pretty; my %data; while (<DATA>) { chomp; my ($code, $date, $time) = split /\s+/; next if ! defined $time; push @{$data{$date}}, [$code, $time]; } my $cgi = CGI->new(); my $tableContents; for (sort keys %data) { $tableContents .= $cgi->Tr ($cgi->td ('&nbsp;')); $tableContents .= $cgi->Tr ($cgi->td ($_)); for (sort {$a->[1] cmp $b->[1]} @{$data{$_}}) { $tableContents .= $cgi->Tr ( $cgi->td ($_->[0]), $cgi->td ($_->[1]) ); }; } #print $cgi->header (); print $cgi->start_html (); print $cgi->table ($tableContents); print $cgi->end_html (); __DATA__ CA642997 2007-01-29 03:05:00 CA651167 2007-01-29 03:05:00 CA651038 2007-01-29 19:00:00 CA650995 2007-01-30 19:00:00 CA652568 2007-01-31 01:05:00 CA652880 2007-01-31 01:30:00 CA652884 2007-01-31 06:00:00 CA643602 2007-02-01 00:30:00 CA652881 2007-02-01 01:00:00

    which prints output that renders as (having stripped off headers and stuff for posting here):

     
    2007-01-29
    CA642997 03:05:00
    CA651167 03:05:00
    CA651038 19:00:00
     
    2007-01-30
    CA650995 19:00:00
     
    2007-01-31
    CA652568 01:05:00
    CA652880 01:30:00
    CA652884 06:00:00
     
    2007-02-01
    CA643602 00:30:00
    CA652881 01:00:00

    DWIM is Perl's answer to Gödel
Re: help formatting output of particular loop
by tinita (Parson) on Jan 29, 2007 at 08:47 UTC
    untested (it seems your rows are already sorted):
    my $last_date; for my $row (@rows) { if ($row->{start_date} ne $last_date) { print "$row->{start_date}\n"; $last_date = $row->{start_date}; } printf "%8s %8s", $row->{id_number}, $row->{start_time}; }
      geez i do have brain damage.

      what you have written i already figured out (thanks, though). but i completely forgot to add a crucial component to this problem.

      if the start_time of the following day is earlier that 09:00, i want it printed with the previous day. for example, if this were the output:
      id_number CA456789 2007-01-29 16:00:00 CA456712 2007-01-30 03:00:00
      i would like it to be output like this:
      2007-01-29 CA456789 16:00:00 CA456712 03:00:00
      thanks again for you help
        Modify tinita's code as follows
        if ($row->{start_date} ne $last_date && (split/:/,$row->start_time)[0] + > 9) {

        update: Oops. That will output incorrect results if all entries for a day are from before 9:00. Make a hash keyed with unix timestamps of each date, push each entry onto an array for the appropriate day:

        use Time::Local; ... for my $row (@rows) { my @l = reverse split /-/, $row->{start_date}; $l[1]--; # months range is 0..11 my $key = timelocal(0,0,0,@l); my $line = join("\t", $row->{id_number}, $row->{start_time}); # wh +atever formatting if(split/:/,$row->start_time)[0] > 9) { push @{$hash{$key-86400}}, $line; } else { push @{$hash{$key}}, $line; } } foreach my $key (sort %hash) { my @l = (localtime $key)[5,4,3]; $l[1]++; # month... print join('-', @l), "\n"; print $_,"\n" for @{$hash{$key}}; }

        --shmem

        _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                      /\_¯/(q    /
        ----------------------------  \__(m.====·.(_("always off the crowd"))."·
        ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
        A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (4)
As of 2022-05-24 16:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Do you prefer to work remotely?



    Results (84 votes). Check out past polls.

    Notices?