如何优化此perl脚本/使其更加地道?

如何优化此perl脚本/使其更加地道?,perl,Perl,我需要根据作业id将一个文件中的数据拆分为其他文件。该文件和两个帮助文件的结构如下: # data.txt - data file - node,timestamp,data 1,1516,25 2,1845,24 3,1637,26 4,1342,74 5,1426,63 6,1436,23 7,1732,64 1,1836,83 2,1277,12 3,2435,62 4,2433,47 5,2496,52 6,2142,69 7,2176,53 # job.txt - job timin

我需要根据作业id将一个文件中的数据拆分为其他文件。该文件和两个帮助文件的结构如下:

# data.txt - data file - node,timestamp,data
1,1516,25
2,1845,24
3,1637,26
4,1342,74
5,1426,63
6,1436,23
7,1732,64
1,1836,83
2,1277,12
3,2435,62
4,2433,47
5,2496,52
6,2142,69
7,2176,53

# job.txt - job timing - job,startts,endts
1234,1001,2000
5678,2001,2500

# node.txt - node to job map - job,node
1234,1
1234,2
1234,3
1234,4
1234,5
5678,3
5678,4
5678,5
5678,6
5678,7
为了将数据文件中的一行映射到相应的新文件,必须进行两次转换。首先,必须使用数据时间戳来确定正在运行的作业。其次,必须检查正在运行的作业列表,以确定数据引用的节点的所有者。这是我的解决方案:

use strict;
use warnings;

my @timing = ( );
my %nodes = ( );
my %handles = ( );

### array of arrays containing job, start time, and end time
open JOB, "<job.txt" or die "can't open jobfile, $!";
while (<JOB>) {
    my @fields = split /,/;  #/ stop SO highliter
    my @array = ($fields[0], $fields[1], $fields[2]);

    push @timing, \@array;
}
close JOB;

### map job -> array of nodes
open NID "<node.txt" or die "can't open nidfile";
while (<NID>) {
    my @fields = split /,/;  #/

    if (!exists $nodes{$fields[0]}) { $nodes{$fields[0]} = (); }
    push @{$nodes{$fields[0]}}, $fields[1];
}
close NID;

### split data
open DATA, "<data.txt" or die "Couldn't open file all.pow, $!";
while (<DATA>) {
    my @fields = split /,/;  #/

    my @jobs = grep {$fields[1] >= $_->[1] && $fields[1] <= $_->[2]} @timing;
    scalar @jobs > 0 or next;
    my $jid = (grep {!exists $nodes{$fields[0]}} @jobs)[0][0];

    ### create and memoize file handles
    if (!exists $handles{$jid}) {
        open my $temp, ">$jid.txt" or die "Can't open jfile $jid, $!";
        $handles{$jid} = $temp;
    }
    print {$handles{$jid}} "$fields[1],fields[2]";
}
close DATA;
使用严格;
使用警告;
我的@timing=();
我的%nodes=();
我的%handles=();
###包含作业、开始时间和结束时间的数组数组

open JOB,“至于效率,如果这段代码经常写入文件(并且需要动态打开许多文件),我看不出有什么方法可以显著提高速度。允许预处理或后处理可能会有所帮助,但这取决于更广泛的上下文

下面是一些编码点的快速挖掘。按外观顺序排列

  • “初始化”数组和散列到空列表是完全没有用的;只需声明它们

  • 始终和三个参数
    打开
    (就像你在写作中所做的那样)

    这是因为:如果一个对象在左值上下文中被取消引用(当它是可修改的),那么它是在未定义的情况下被创建的。这是一个复杂的功能。接近您的使用是;也可以看到这个,以及它的链接

  • 使用数组或列表,而不是

    my @array = ($fields[0], $fields[1], $fields[2]);
    
    能行

    my @array = @fields[0,1,2];   # or @fields[0..2] in this case
    
    那么你也可以这样做

    push @timing, [ @fields[0..2] ];
    

    因为没有创建中间数组,所以哪两个更有效。但后两个灵活性较低,限制了中间处理或检查的可能性。如果这就是您要做的所有事情,那么

    my @timing = map { [ (split /,/)[0..2] ] } <$job_fh>;
    
    不需要
    标量
    ,您可以编写

    @jobs > 0 or next;
    
    减少到

    @jobs or next;
    
    但我更愿意写的是

    next if not @jobs;   # or:  next unless @jobs;
    
    使用(“后缀语法”)



†列表处于列表上下文中(见上面的链接)由
map
施加,因此它返回所有行

Add and。然后返回。可能更适合@choroba。这两个都是在我的原始脚本中完成的,但在粘贴到问题中时被忽略了。我会修复它。很好。另外,提供示例数据而不是它们的描述。请参阅。代码检查与堆栈溢出无关。是否我使用的文件句柄和词法句柄之间的差异与全局变量和局部变量之间的差异相同?@AzureHeights加上更多,因为这是关于文件句柄的。简言之,您几乎不需要typeglobs@AzureHeights添加到文档的链接(一个用于typeglobs,另一个用于词法)
scalar @jobs > 0 or next;
@jobs > 0 or next;
@jobs or next;
next if not @jobs;   # or:  next unless @jobs;