解决此问题的最佳做法是什么?
if (... )
{
push (@{$hash{'key'}}, @array ) ;
}
else
{
$hash{'key'} ="";
}
存储一个元素的坏习惯是数组还是一个只是哈希中的双引号?
解决此问题的最佳做法是什么?
if (... )
{
push (@{$hash{'key'}}, @array ) ;
}
else
{
$hash{'key'} ="";
}
存储一个元素的坏习惯是数组还是一个只是哈希中的双引号?
使用显式数组引用可能更简单:
my $arr_ref = \@array;
$hash{'key'} = $arr_ref;
实际上,执行上述操作并使用push
相同的数据结构:
my @array = qw/ one two three four five /;
my $arr_ref = \@array;
my %hash;
my %hash2;
$hash{'key'} = $arr_ref;
print Dumper \%hash;
push @{$hash2{'key'}}, @array;
print Dumper \%hash2;
这给出了:
$VAR1 = {
'key' => [
'one',
'two',
'three',
'four',
'five'
]
};
$VAR1 = {
'key' => [
'one',
'two',
'three',
'four',
'five'
]
};
使用显式数组引用使用更少的字符并且比push @{$hash{'key'}}, @array
构造 IMO 更容易阅读。
编辑:对于您的else{}
块,分配空字符串可能不太理想。跳过构造会容易得多if-else
,稍后当您访问散列中的值时,进行if( defined( $hash{'key'} ) )
检查。这更接近标准 Perl 习惯用法,而且您不会浪费内存在散列中存储空字符串。
相反,您将不得不使用ref()
来找出您的价值中有哪些类型的数据,这比仅进行定义性检查要清楚。
我不确定我是否理解你的问题,但我会按照现在的要求逐字回答......
my @array = (1, 2, 3, 4);
my $arrayRef = \@array; # alternatively: my $arrayRef = [1, 2, 3, 4];
my %hash;
$hash{'key'} = $arrayRef; # or again: $hash{'key'} = [1, 2, 3, 4]; or $hash{'key'} = \@array;
问题的症结在于数组或散列采用标量值......因此您需要引用您的数组或散列并将其用作值。
有关详细信息,请参阅perlref和perlreftut。
编辑:是的,您可以为其他键添加空字符串作为某些键和引用的值(到数组或散列,甚至是标量、typeglobs/文件句柄或其他标量。无论哪种方式)。它们仍然是标量。
您需要查看ref
用于确定如何消除引用类型和普通标量之间的歧义的函数。
我不确定你的目标是什么,但有几件事需要考虑。
首先,如果你要存储一个数组,你想存储对原始值的引用还是原始值的副本?在任何一种情况下,我都更喜欢避免取消引用语法并尽可能地引用:
$hash{key} = \@array; # just a reference
use Clone; # or a similar module
$hash{key} = clone( \@array );
接下来,您是否要添加到已经存在的值,即使它是单个值?如果您要拥有数组值,即使您只有一个元素,我也会将所有值都设为数组。然后你不必决定做什么,你删除一个特殊情况:
$hash{key} = [] unless defined $hash{key};
push @{ $hash{key} }, @values;
这可能是您的“最佳实践”答案,这通常是消除尽可能多的特殊情况和额外逻辑的技术。当我在一个模块中做这种事情时,我通常有一个add_value
方法来封装这种魔法,我不必多次看到它或输入它。
如果哈希键中已经有一个非引用值,那也很容易修复:
if( defined $hash{key} and ! ref $hash{key} ) {
$hash{key} = [ $hash{key} ];
}
如果您已经有想要在数组中的非数组引用值,您可以执行类似的操作。也许您希望匿名哈希成为数组元素之一:
if( defined $hash{key} and ref $hash{key} eq ref {} ) {
$hash{key} = [ $hash{key} ];
}
处理修改后的符号:
if (... )
{
push (@{$hash{'key'}}, @array);
}
else
{
$hash{'key'} = "";
}
我们可以立即告诉您,您没有遵循保护新手(和专家!)免于犯错的标准建议。您正在使用符号引用,这不是一个好主意。
use strict;
use warnings;
my %hash = ( key => "value" );
my @array = ( 1, "abc", 2 );
my @value = ( 22, 23, 24 );
push(@{$hash{'key'}}, @array);
foreach my $key (sort keys %hash) { print "$key = $hash{$key}\n"; }
foreach my $value (@array) { print "array $value\n"; }
foreach my $value (@value) { print "value $value\n"; }
这不运行:
Can't use string ("value") as an ARRAY ref while "strict refs" in use at xx.pl line 8.
我不确定我能弄清楚你想要达到的目标。即使您删除了“使用严格;” 警告,显示的代码未检测到push
操作的更改。
use warnings;
my %hash = ( key => "value" );
my @array = ( 1, "abc", 2 );
my @value = ( 22, 23, 24 );
push @{$hash{'key'}}, @array;
foreach my $key (sort keys %hash) { print "$key = $hash{$key}\n"; }
foreach my $value (@array) { print "array $value\n"; }
foreach my $value (@value) { print "value $value\n"; }
foreach my $value (@{$hash{'key'}}) { print "h_key $value\n"; }
push @value, @array;
foreach my $key (sort keys %hash) { print "$key = $hash{$key}\n"; }
foreach my $value (@array) { print "array $value\n"; }
foreach my $value (@value) { print "value $value\n"; }
输出:
key = value
array 1
array abc
array 2
value 22
value 23
value 24
h_key 1
h_key abc
h_key 2
key = value
array 1
array abc
array 2
value 22
value 23
value 24
value 1
value abc
value 2
我不确定那里发生了什么。
如果您的问题是如何将之前存储的空字符串值替换为可以将值推送到其中的数组,那么这可能是最好的方法:
if ( ... ) {
my $r = \$hash{ $key }; # $hash{ $key } autoviv-ed
$$r = [] unless ref $$r;
push @$$r, @values;
}
else {
$hash{ $key } = "";
}
%hash
.