且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Perl:在复杂哈希中生成数组

更新时间:2022-06-24 10:10:12

这应该适合你.

#!/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";
        }
    }
}

注意事项:

  • strict警告 pragmas
  • List::Util 模块获取求和函数
  • 将数组放入标量上下文中以获取数组中的项数(在 avg 函数中)
  • 更安全的三个参数版本的 open
  • 词法文件句柄(而不是旧的裸字样式文件句柄)
  • 首先在循环外读取头文件,以避免在循环内有特殊的逻辑
  • 使用 hash slice 将文件数据放入结构化记录中立>
  • 避免使用 split 的第三个参数分割不必要的时间立>
  • 通过只在列表赋值中指定我们想要捕获的变量来避免无用的变量
  • 使用 grep 防止将 DATE 和 TIME 键放入 %monthData
  • 嵌套的 for 循环每个处理哈希中的一个级别
  • strict and warnings pragmas
  • List::Util module to get the sum function
  • putting an array in scalar context to get the number of items in the array (in the avg function)
  • the safer three argument version of open
  • the lexical filehandle (rather than the old bareword style filehandle)
  • reading the headers first outside the loop to avoid having to have special logic inside it
  • using a hash slice to get the file data into a structured record
  • avoiding splitting the time more than necessary with the third argument to split
  • avoiding useless variables by only specifying the variable we want to catch in the list assignment
  • using grep to prevent the DATE and TIME keys from being put in %monthData
  • the nested for loops each dealing with a level in the hash