我想让我的脚本以尽可能最佳的效率和速度运行。以下是我创建HoA的方法。
use strict; use warnings; open(my $fh, '<', 'file.txt') or die $!;
my %HoA;
while (<$fh>){
$_=~ s/\r//;
chomp;
my @cols = split(/\t/, $_);
my $key = shift @cols;
push( @{$HoA{$key}, @cols );
}
假设它提供以下数据结构
%HoA = (
'C1' => ['1', '3', '3', '3'],
'C2' => ['3','2'],
'C3' => ['1','3','3','4','5','5'],
'C4' => ['3','3','4'],
'C5' => ['1'],
);
现在假设对于HoA中的每个键,我想将它的值(数组)和整个HoA传递给一个名为compute
的子例程。
以下是我目前正在做的事情。
foreach my $key ( keys %HoA ) {
compute($HoA{$key}, \%HoA); # on the first iteration, this actually passes an aref to [1,3,3,3]
}
显然$ HoA {$ key}已经是该特定$ key的每个值的数组引用。
如果是这种情况,那么在执行以下方面的效率方面是否有任何优势
push( @{$HoA{$key}, \@cols );
它产生以下数据结构
%HoA = (
'C1' => [ ['1', '3'], ['3', '3'] ],
'C2' => [ ['3','2'] ],
'C3' => [ ['1','3'], ['3','4'], ['5','5'] ],
'C4' => [ ['3','3','4'] ],
'C5' => [ ['1'] ],
);
这会让我的脚本运行得更快吗?如果是这样,那么在这种情况下如何将每个键的值(array_ref)传递给子例程?一旦它进入子程序,如何在不解除引用子程序中的整个array_ref的情况下访问数组中的各个元素?另外,对于$ hash_ref,我如何访问每个array_ref?
以下是我目前的方式
sub compute{
# takes one param: an arrayref
my ($array_ref, $hash_ref) = @_;
for my $p ( @{ $array_ref) ) {
# do stuff
}
for my $x ( values %{ %hash_ref)) {
# do stuff
}
}
答案 0 :(得分:1)
由于代码中的解引用,这可能会使代码运行得更慢。此外,您需要展平每个哈希条目所指向的数组中包含的数组,如下所示:
my %h = ( a => [ [1, 2], [3, 4] ], b => [ [2, 3], [5, 6] ]);
my $key = 'a';
my @all_items;
@all_items = map { @$_ } @{$h{$key}};
仅根据经验,在Perl中取消引用对象(即数组)可能非常昂贵,因此使用较少引用的第一种方法应该更快。但你可以实际掌握这些东西。最好的方法是编写代码,然后担心在整个代码分析后真正重要的部分。
答案 1 :(得分:1)
如果是这种情况,那么在执行以下方面的效率方面是否有任何优势
push( @{$HoA{$key}, \@cols );
没有。首先正确创建数据结构
push @{ $HoA{$key} }, @cols; # Copies the number to the anon array.
compute($_, \%HoA) for values %HoA;
比以后重新创建正确的数据结构更好。
push @{ $HoA{$key} }, \@cols;
compute([ map @$_, @$_ ], \%HoA) for values %HoA; # But so does this.
通过切换,你最终会对你正在做的工作做一个正确的超集。
正如评论中所提到的,你正在优化错误的东西。你说你的程序需要30-40秒才能运行。即使您减少了将文件加载到零所需的时间,您的程序仍需要29-39秒。