Here are 2 additional solutions. One uses
DateTime and the other uses
Date::Parse and
POSIX. I don't know about speed, but you could try them out and see. Also, which is the most easy to read might be a consideration, (as you stated).
#!/usr/bin/perl
use strict;
use warnings;
use DateTime::Format::Strptime;
my $dt = DateTime::Format::Strptime->new( pattern => '%Y.%m.%d %H:%M')
+;
chomp(my @line = split /,/, <DATA>);
my @data = \@line;
my $beg = $dt->parse_datetime("@line[0,1]")->truncate( to => 'hour' );
my $end = $beg->clone->add(hours => 12);
printf "%s -+- %s\n", map tr/T/ /r, $beg, $end;
while (<DATA>) {
chomp(my @line = split /,/);
my $date = $dt->parse_datetime("@line[0,1]")->truncate( to => 'hou
+r' );
if ($date < $end) {
push @data, \@line;
}
else {
process(@data);
@data = \@line;
$end = $date->clone->add(hours => 12);
printf "%s -+- %s\n", map tr/T/ /r, $date, $end;
}
}
process(@data);
sub process {
my @data = @_;
# do somthing with data
my @sum;
my @idx = 2 .. 5;
for my $line (@data) {
for my $col (@idx) {
$sum[$col] += $line->[$col];
}
}
printf "Avg of %d lines", scalar @data;
print +(map {sprintf "%10.5f", $sum[$_] / @data} @idx), "\n";
}
The Date::Parse solution is nearly the same.
#!/usr/bin/perl
use strict;
use warnings;
use Date::Parse qw/ str2time /;
use POSIX qw/ strftime /;
chomp(my @line = split /,/, <DATA>);
my @data = \@line;
my $beg = str2time("@line[0,1]");
$beg = int($beg / 3600) * 3600; # truncate minutes and seconds
my $end = $beg + 12 * 60 * 60; # add 12 hours
printf "%s -+- %s\n",
map {strftime "%Y-%m-%d %H:%M:%S", localtime $_} $beg,$end;
while (<DATA>) {
chomp(my @line = split /,/);
my $date = str2time("@line[0,1]");
$date = int($date / 3600) * 3600; # truncate minutes and seconds
if ($date < $end) {
push @data, \@line;
}
else {
process(@data);
@data = \@line;
$end = $date + 12 * 60 * 60;
printf "%s -+- %s\n",
map {strftime "%Y-%m-%d %H:%M:%S", localtime $_} $date, $e
+nd;
}
}
process(@data);
sub process {
my @data = @_;
# do somthing with data
my @sum;
my @idx = 2 .. 5;
for my $line (@data) {
for my $col (@idx) {
$sum[$col] += $line->[$col];
}
}
printf "Avg of %d lines", scalar @data;
print +(map {sprintf "%10.5f", $sum[$_] / @data} @idx), "\n";
}
__DATA__
2011.01.13,21:25,1.33508,1.33524,1.33470,1.33494,391
2011.01.13,21:30,1.33494,1.33506,1.33447,1.33453,318
2011.01.13,21:35,1.33453,1.33483,1.33417,1.33434,426
2011.01.13,21:40,1.33434,1.33468,1.33417,1.33467,309
2011.01.13,21:45,1.33471,1.33493,1.33465,1.33465,233
2011.01.13,21:50,1.33465,1.33475,1.33443,1.33463,184
2011.01.13,21:55,1.33463,1.33519,1.33463,1.33493,344
2011.01.13,22:00,1.33494,1.33563,1.33489,1.33524,318
2011.01.13,22:05,1.33524,1.33551,1.33512,1.33549,182
2011.01.14,22:05,1.33524,1.33551,1.33512,1.33549,182
These produced the output:
C:\Old_Data\perlp>perl t33.pl
2011-01-13 21:00:00 -+- 2011-01-14 09:00:00
Avg of 9 lines 1.33478 1.33509 1.33458 1.33482
2011-01-14 22:00:00 -+- 2011-01-15 10:00:00
Avg of 1 lines 1.33524 1.33551 1.33512 1.33549
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.