我有下面的代码。我想为每个版本值分配但不知何故我不知道我做错了什么。
%buildsMap = ();
#read schedule
opendir (DIR, $buildsDir) or die $!;
while ( my $file = readdir DIR ) {
if (($file =~ /(V\d\d\d.*)-DVD/) || ($file =~ /(V\d\d\d.*)/)) {
foreach $version(@versionS){
if ($1 eq $version ){
@temp = @{$buildsMap{$version}};
push @temp,$file;
@{$buildsMap{$version}} = @temp;
}
}
}
}
如果我想使用此hashmap中的键,则可以。请指教我。
答案 0 :(得分:3)
第一项业务,开启严格和警告。这将发现任何拼写错误变量和其他错误。这里的主要问题是您必须声明所有变量。修复所有问题并打印出结果%buildMap
,我们有一个最小的可行示例。
use strict;
use warnings;
use v5.10;
my $buildsDir = shift;
my @versionS = qw(V111 V222 V333);
my %buildsMap = ();
#read schedule
opendir (DIR, $buildsDir) or die $!;
while ( my $file = readdir DIR ) {
if (($file =~ /(V\d\d\d.*)-DVD/) || ($file =~ /(V\d\d\d.*)/)) {
foreach my $version (@versionS) {
if ($1 eq $version ){
my @temp = @{$buildsMap{$version}};
push @temp,$file;
@{$buildsMap{$version}} = @temp;
}
}
}
}
for my $version (keys %buildsMap) {
my $files = $buildsMap{$version};
say "$version @$files";
}
出现错误Can't use an undefined value as an ARRAY reference at test.plx line 15.
。这就是这条线。
my @temp = @{$buildsMap{$version}};
这里的问题是您如何使用数组引用。该特定行失败,因为如果$buildsMap{$version}
没有条目,则您尝试取消引用任何内容并且Perl不会允许这样做,而不是正常的取消引用。我们可以解决这个问题,但是有更好的方法来处理列表的哈希。这就是你所拥有的。
my @temp = @{$buildsMap{$version}};
push @temp,$file;
@{$buildsMap{$version}} = @temp;
将所有文件名复制到@temp
,使用@temp
和更舒适的语法,然后将其复制回来。它对内存和代码量的效率低下。相反,我们可以做到这一点。首先,如果需要,将值初始化为空数组引用,然后直接将文件推送到该数组引用。
$buildsMap{$version} ||= [];
push @{$buildsMap{$version}}, $file;
||=
是or-equals
运算符。如果左侧是假的,它只会进行分配。它经常用于设置默认值。你也可以写$buildsMap{$version} = [] if !$buildsMap{$version}
,但这很快就会变得多余。
但我们甚至不需要这样做! push
是一个特例。为方便起见,您可以取消引用空值并将其传递给push
!因此,我们不需要初始化程序,只需按下即可。
push @{$buildsMap{$version}}, $file;
虽然代码有效,但可以提高效率。不是为每个文件名扫描@versionS
,如果有很多文件或许多版本,可能会浪费,可能会浪费。现在不需要内循环了。
my %versionS = ( 'V111' => 1, 'V222' => 2, 'V333' => 3 );
...
if (($file =~ /(V\d\d\d.*)-DVD/) || ($file =~ /(V\d\d\d.*)/)) {
my $version = $1;
if ($versionS{$version}){
push @{$buildsMap{$version}}, $file;
}
}