解决此问题的最佳做法是什么?
if (... )
{
push (@{$hash{'key'}}, @array ) ;
}
else
{
$hash{'key'} ="";
}
存储一个元素的不良做法是数组还是一个只是哈希的双引号?
答案 0 :(得分:2)
使用显式数组引用可能更简单:
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()
来查找您的值中包含的数据类型,这不仅仅是进行定义检查。
答案 1 :(得分:2)
我不确定我理解你的问题,但我现在会按照字面意思回答......
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 / filehandles或其他标量。无论哪种方式)的值,以用于其他键。他们都还是标量。
您需要查看ref
函数,了解如何消除引用类型和普通标量之间的歧义。
答案 2 :(得分:1)
我不确定你的目标是什么,但有几件事需要考虑。
首先,如果要存储数组,是否要存储对原始值的引用或原始值的副本?在任何一种情况下,我都希望避免使用解引用语法并在可以的时候接受引用:
$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} ];
}
答案 3 :(得分:0)
处理修订后的表示法:
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.
我不确定我能弄清楚你想要达到的目标。即使你删除'use strict;'警告,显示的代码未检测到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
我不确定那里发生了什么。
答案 4 :(得分:0)
如果您的问题是如何替换之前存储的空字符串值,您可以使用数组推送您的值,这可能是最好的方法:
if ( ... ) {
my $r = \$hash{ $key }; # $hash{ $key } autoviv-ed
$$r = [] unless ref $$r;
push @$$r, @values;
}
else {
$hash{ $key } = "";
}
%hash
中存储的整个事物。