我需要将一个平面键列表转换为嵌套哈希,如下所示:
我的 $hash = {};
我的@array = qw(key1 key2 lastKey Value);
ToNestedHash($hash, @array);
会这样做:
$hash{'key1'}{'key2'}{'lastKey'} = "值";
我需要将一个平面键列表转换为嵌套哈希,如下所示:
我的 $hash = {};
我的@array = qw(key1 key2 lastKey Value);
ToNestedHash($hash, @array);
会这样做:
$hash{'key1'}{'key2'}{'lastKey'} = "值";
sub to_nested_hash {
my $ref = \shift;
my $h = $$ref;
my $value = pop;
$ref = \$$ref->{ $_ } foreach @_;
$$ref = $value;
return $h;
}
解释:
我们知道:
my $h = {}; my $a = [];
)。这样做可能更明确:
foreach my $key ( @_ ) {
my $lvl = $$ref = {};
$ref = \$lvl->{ $key };
}
但由于重复使用这些参考成语,我完全按原样写了那行,并在发布前对其进行了测试,没有错误。
至于替代方案,以下版本“更容易”(想出)
sub to_nested_hash {
$_[0] //= {};
my $h = shift;
my $value = pop;
eval '$h'.(join '', map "->{\$_[$i]}", 0..$#_).' = $value';
return $h;
}
但慢了大约 6-7 倍。
我认为这段代码更好 - 更适合移动到类方法中,并且可以根据提供的参数设置一个值。否则选择的答案很整洁。
#!/usr/bin/env perl
use strict;
use warnings;
use YAML;
my $hash = {};
my @array = qw(key1 key2 lastKey);
my $val = [qw/some arbitrary data/];
print Dump to_nested_hash($hash, \@array, $val);
print Dump to_nested_hash($hash, \@array);
sub to_nested_hash {
my ($hash, $array, $val) = @_;
my $ref = \$hash;
my @path = @$array;
print "ref: $ref\n";
my $h = $$ref;
$ref = \$$ref->{ $_ } foreach @path;
$$ref = $val if $val;
return $h;
}
谢谢你的好东西!!!
我用递归的方式做到了:
sub Hash2Array
{
my $this = shift;
my $hash = shift;
my @array;
foreach my $k(sort keys %$hash)
{
my $v = $hash->{$k};
push @array,
ref $v eq "HASH" ? $this->Hash2Array($v, @_, $k) : [ @_, $k, $v ];
}
return @array;
}
在所有这些解决方案之间进行性能比较会很有趣......
我认为制作了一个更好的斧头版本。至少没有 -> 和 \shift 对我来说更容易理解。3 行没有子程序。
带子程序
sub to_nested_hash {
my $h=shift;
my($ref,$value)=(\$h,pop);
$ref=\%{$$ref}{$_} foreach(@_);
$$ref=$value;
return $h;
}
my $z={};
to_nested_hash($z,1,2,3,'testing123');
无子程序
my $z={};
my $ref=\$z; #scalar reference of a variable which contains a hash reference
$ref=\%{$$ref}{$_} foreach(1,2,3); #keys
$$ref='testing123'; #value
#with %z hash variable just do double backslash to get the scalar reference
#my $ref=\\%z;
结果:
$VAR1 = {
'1' => {
'2' => {
'3' => 'testing123'
}
}
};