Perl:如何将数组转换为嵌套的哈希键

时间:2012-07-16 13:13:39

标签: perl perl-data-structures

我需要将平面键列表转换为嵌套哈希,如下所示:

  

my $ hash = {};

     

我的@array = qw(key1 key2 lastKey Value);

     

ToNestedHash($ hash,@ array);

会这样做:

  

$ hash {'key1'} {'key2'} {'lastKey'} =“价值”;

4 个答案:

答案 0 :(得分:9)

sub to_nested_hash {
    my $ref   = \shift;  
    my $h     = $$ref;
    my $value = pop;
    $ref      = \$$ref->{ $_ } foreach @_;
    $$ref     = $value;
    return $h;
}

说明:

  • 将第一个值作为hashref
  • 将最后一个值作为要分配的值
  • 其余的都是钥匙。
  • 然后创建对基本哈希的 SCALAR 引用。
  • 反复:
    • 取消引用指针以获取哈希值(第一次)或将指针自动生成为哈希值
    • 获取密钥的哈希位置
    • 并将标量引用分配给哈希槽。
    • (下一次将自动生效到指示的哈希值。)
  • 最后,通过引用最里面的插槽,分配值。

我们知道:

  • 哈希或数组的占用者只能是标量或引用。
  • 参考是各种标量。 (my $h = {}; my $a = [];)。
  • 所以,\ $ h-> {$ key}是对堆上标量槽的引用,可能是自动生成的。
  • 嵌套哈希的“级别”可以自动生成哈希引用,如果我们这样解决它。

这样做可能更明确:

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倍。

答案 1 :(得分:0)

好事的Thxs !!!

我以递归的方式做到了:

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;
}

在所有这些解决方案之间进行性能比较会很有趣......

答案 2 :(得分:0)

我认为这个代码更好 - 更适合移入类方法,并可选择设置一个值,具体取决于提供的参数。否则所选答案很整洁。

#!/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;
}

答案 3 :(得分:0)

我认为是斧头侠的更好版本。至少不需要->和\ 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'
                          }
                 }
        };