为了使我的数据更易于访问,我希望将表格数据存储在复杂的哈希中。当脚本循环遍历我的数据时,我正在尝试增加'HoHoHoA'。根据'perldsc'中的指南:
push @ { $hash{$column[$i]}{$date}{$hour} }, $data[$i];
脚本编译并运行没有问题,但不会向哈希添加任何数据:
print $hash{"Frequency Min"}{"09/07/08"}{"15"};
即使密钥存在,也不返回任何内容。在哈希上运行'exists'表示它不存在。
我正在阅读的数据文件如下所示:
DATE TIME COLUMN1 COLUMN2 COLUMN3...
09/06/2008 06:12:56 56.23 54.23 56.35...
09/06/2008 06:42:56 56.73 55.28 54.52...
09/06/2008 07:12:56 57.31 56.79 56.41...
09/06/2008 07:42:56 58.24 57.30 58.86...
.
.
.
我希望将任何给定日期和小时的数组中每列的值组合在一起,因此{COLUMN},{DATE}和{HOUR}的三个哈希值。
结果结构如下所示:
%monthData = (
"COLUMN1" => {
"09/06/2008" => {
"06" => [56.23,56.73...],
"07" => [57.31,58.24...]
}
},
"COLUMN2" => {
"09/06/2008" => {
"06" => [54.23,55.28...],
"07" => [56.79,57.30...]
}
},
"COLUMN3" => {
"09/06/2008" => {
"06" => [56.35,54.52...],
"07" => [56.41,58.86...]
}
}
);
看看我的代码:
use feature 'switch';
open DATAFILE, "<", $fileName or die "Unable to open $fileName !\n";
my %monthData;
while ( my $line = <DATAFILE> ) {
chomp $line;
SCANROWS: given ($row) {
when (0) { # PROCESS HEADERS
@headers = split /\t\t|\t/, $line;
}
default {
@current = split /\t\t|\t/, $line;
my $date = $current[0];
my ($hour,$min,$sec) = split /:/, $current[1];
# TIMESTAMP FORMAT: dd/mm/yyyy\t\thh:mm:ss
SCANLINE: for my $i (2 .. $#headers) {
push @{ $monthData{$headers[$i]}{$date}{$hour} }, $current[$i];
}
}
}
}
close DATAFILE;
foreach (@{ $monthData{"Active Power N Avg"}{"09/07/08"}{"06"} }) {
$sum += $_;
$count++;
}
$avg = $sum/$count; # $sum and $count are not initialized to begin with.
print $avg; # hence $avg is also not defined.
希望我的需要足够明确。如何将值附加到这些子哈希中的数组?
答案 0 :(得分:8)
这应该为你做。
#!/usr/bin/perl
use strict;
use warnings;
use List::Util qw/sum/;
sub avg { sum(@_) / @_ }
my $fileName = shift;
open my $fh, "<", $fileName
or die "Unable to open $fileName: $!\n";
my %monthData;
chomp(my @headers = split /\t+/, <$fh>);
while (<$fh>) {
chomp;
my %rec;
@rec{@headers} = split /\t+/;
my ($hour) = split /:/, $rec{TIME}, 2;
for my $key (grep { not /^(DATE|TIME)$/ } keys %rec) {
push @{ $monthData{$key}{$rec{DATE}}{$hour} }, $rec{$key};
}
}
for my $column (keys %monthData) {
for my $date (keys %{ $monthData{$column} }) {
for my $hour (keys %{ $monthData{$column}{$date} }) {
my $avg = avg @{ $monthData{$column}{$date}{$hour} };
print "average of $column for $date $hour is $avg\n";
}
}
}
要注意的事项:
答案 1 :(得分:2)
我希望以下程序填充您想要的数据结构:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
open my $fh, '<', 'input' or die $!;
my @headers;
for ( split /\t/, ~~ <$fh> ) {
chomp;
push @headers, $_ unless /^\t?$/;
}
my %monthData;
while (<$fh>) {
my @line;
for ( split /\t/ ) {
chomp;
push @line, $_ unless /^\t?$/;
}
for my $i ( 2 .. $#headers ) {
my ($hour) = split /:/, $line[1];
push @{ $monthData{ $headers[$i] }->{ $line[0] }->{$hour} }, $line[$i];
}
}
print Dumper \%monthData;
答案 2 :(得分:1)
以下是我编写程序的方法。
#! /usr/bin/env perl
use strict;
use warnings;
use 5.010; # for say and m'(?<name>)'
use YAML;
use Data::Dump 'dump';
my(%data,%original);
while( my $line = <> ){
next unless $line =~ m'
^ \s*
(?<day> 0?[1-9] | [12][0-9] | 3[0-1] ) /
(?<month> 0?[1-9] | 1[0-2] ) /
(?<year> [0-9]{4} )
\s+
(?<hour> 0?[1-9] | 1[0-9] | 2[0-4] ) :
(?<minute> 0?[1-9] | [1-5][0-9] ) :
(?<second> 0?[1-9] | [1-5][0-9] )
\s+
(?<columns> .* )
'x;
my @columns = split ' ', $+{columns};
push @{
$data{ $+{year} }
{ $+{month} }
{ $+{day} }
{ $+{hour} }
}, \@columns; # or [@columns]
# If you insist on having it in that data structure you can do this:
my $count = 1;
my $date = "$+{day}/$+{month}/$+{year}";
for my $column ( @columns ){
my $col = 'COLUMN'.$count++;
push @{ $original{$col}{$date}{$+{hour}} }, $column;
}
}
say Dump \%data, \%original; # YAML
say dump \%data, \%original; # Data::Dump
DATE TIME COLUMN1 COLUMN2 COLUMN3 09/06/2008 06:12:56 56.23 54.23 56.35 09/06/2008 06:42:56 56.73 55.28 54.52 09/06/2008 07:12:56 57.31 56.79 56.41 09/06/2008 07:42:56 58.24 57.30 58.86
“perl program.pl datafile
”或“perl program.pl < datafile
”
--- 2008: 06: 09: 06: - - 56.23 - 54.23 - 56.35 - - 56.73 - 55.28 - 54.52 07: - - 57.31 - 56.79 - 56.41 - - 58.24 - 57.30 - 58.86 --- COLUMN1: 09/06/2008: 06: - 56.23 - 56.73 07: - 57.31 - 58.24 COLUMN2: 09/06/2008: 06: - 54.23 - 55.28 07: - 56.79 - 57.30 COLUMN3: 09/06/2008: 06: - 56.35 - 54.52 07: - 56.41 - 58.86
( { 2008 => { "06" => { "09" => { "06" => [["56.23", "54.23", "56.35"], ["56.73", "55.28", "54.52"]], "07" => [["57.31", "56.79", "56.41"], ["58.24", "57.30", "58.86"]], }, }, }, }, { COLUMN1 => { "09/06/2008" => { "06" => ["56.23", "56.73"], "07" => ["57.31", "58.24"] }, }, COLUMN2 => { "09/06/2008" => { "06" => ["54.23", "55.28"], "07" => ["56.79", "57.30"] }, }, COLUMN3 => { "09/06/2008" => { "06" => ["56.35", "54.52"], "07" => ["56.41", "58.86"] }, }, }, )