我正在研究一个生成多个大型哈希数组(HoAs)数据结构的脚本。我正在尝试优化我的脚本,因为它目前需要花费大量时间才能运行。
我做了一些基准测试。我设法使脚本执行约。通过直接使用@_
而不是将其复制到变量中,利用数组引用和减少子程序调用开销,可以快3.5倍。我还删除了不必要的子程序和冗余变量声明。尽管有这些改进,我还是想让代码运行得更快。
在我的脚本开始时,我解析一个大文件以生成两个HoA数据结构。 关于哈希引用的这些方法中哪一种最可行和最有效? HoA看起来像这样:
%HoA = (
'C1' => ['1', '3', '3', '3'],
'C2' => ['3','2'],
'C3' => ['1','3','3','4','5','5'],
'C4' => ['3','3','4'],
'C5' => ['1'],
);
选项1
解析文件时生成HoAs(见下文)。最后将数组的哈希值放入哈希引用。
my $hash_ref = \%HoA;
选项2
解析文件,使HoA中的每个键都有一个指向array_ref的值。最后将数组的哈希值放入哈希引用。
==============
我觉得选择2是一个很好的方法,但我该怎么做?
以下是我目前正在做的事情。
use strict; use warnings;
open(F1, "file.txt") or die $!;
my %HoA = ();
while (<F1>){
$_=~ s/\r//;
chomp;
my @cols = split(/\t/, $_);
push( @{$HoA{$cols[0]}}, @cols[1..$#cols]);
}
close F1;
我需要一个高效的数据结构,这将有助于我快速查找值和键。此外,我需要能够将键值(数组),键和HoA本身尽可能高效地传递到子程序中。
答案 0 :(得分:4)
%HoA
并且从未使用过。$HoA_ref
并且从未使用过它。$HoA
而没有声明它。始终使用use strict; use warnings;
my %HoA = ();
很愚蠢。s///
和chomp
; $_
,或使用有意义的变量名称。以上所有以及其他一些改进措施都是为了获得:
use strict;
use warnings;
open(my $fh, '<', 'file.txt') or die $!;
my %HoA;
while (<$fh>){
s/\r?\n\z//;
my ($key, @cols) = split /\t/;
push @{ $HoA{$key} }, @cols;
}
答案 1 :(得分:2)
我的经验是,尽可能使用参考资料是最好的。一些补充说明:
如果你需要这个,$_=~ s/\r//;
用于Windows eol兼容性,那么你需要一个更好的perl构建。 ActiveState通常是最强大的。 chomp
应该处理终端cr / lf,或者更确切地说读取的文件应该已经将cr / lf对转换为lf。
Perl shift
是O(1)并且非常快。你可以在这里利用这个优势。
你不能事先告诉你什么是最快的。选项基准是唯一的出路。
尝试单独阅读输入文件而不进行处理。一旦作业受I / O限制,优化就不再有用了。
以下是我的开始:
open(F, "file.txt") or die $!;
my $h = {};
while (<F>){
chomp;
my @cols = split "\t";
my $key = shift @cols;
push @{$h->{$key}}, @cols;
}
close F;
答案 2 :(得分:1)
我认为这是你在你的例子中尝试做的事情。
open(my $fh, "<", "file.txt") or die $!;
my $HoA_ref = {}; # ref will return a HASH
while (my $line = <$fh>) {
$line =~ s/\r//;
chomp $line;
my @cols = split(/\t/, $line);
# shift off first element in the list to use
# as the key
my $key = shift(@cols);
# set value to an array ref of whatever
# is left in the list.
$HoA_ref->{$key} => [@cols];
}
close <$fh>;
值得注意的是,$key
如果在循环浏览文件时出现不止一次,将会被覆盖。
答案 3 :(得分:1)
由于你有大文件,而不是使用while循环,我建议使用模块File::Slurp进行完整的文件诽谤。
File :: Slurp read_file函数尝试使用sysread(检查read_file source code)调用来绕过perl I / O.
my $text = read_file( $file ) ;