在一条指令中将值影响到多级哈希 [英] Affecting a value to a multilevel hash in one instruction

查看:136
本文介绍了在一条指令中将值影响到多级哈希的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种更有效的方法在影响子例程=显示问题标记为'perl' =tag> perl


$ b

 #!/ usr / bin / perl 
使用5.010;
使用strict;

我的@keys = qw / foo bar baz /;
my%hash =(foo => {babel =>'fish'});

影响(\%hash,42);

sub影响{
my $ ref = shift;
$ ref = $ ref-> {$ keys [$ _]} // = {} for(0 .. $#keys - 1);
$ ref-> {$ keys [$#keys]} = shift;
}

使用Data :: Dumper;
打印Dumper \%hash;

预期结果:

  $ VAR1 = {
'foo'=> {
'bar'=> {
'baz'=> 42
},
'babel'=> 'fish'
}
};

我正在考虑这样的事情,但显然它不能像这样工作:

 %hash {@keys} = 42; 

任何想法?

解决方案

如果你真的把密钥传给它,它会更有效率!

  sub dive_val:lvalue {
my $ p = \转移;
$ p = \($$ p-> {$ _})for @_;
$$ p
}

my%hash;
dive_val(\%hash,qw(foo babel))='fish';
dive_val(\%hash,@keys)= 42;

这个实现有两个额外的好处。



首先,您可以使用它来查看数据结构。

  print(dive_val($ hash,@keys) ,\\\
);

其次,它将autovivify其第一个参数。

  my $ hash; 
dive_val($ hash,@keys)= 42;

这个函数已经存在为 Data :: Diver DiveVal

 使用Dive :: Val qw(DiveVal); 

DiveVal(\%hash,map \ $ _,@keys)= 42;






比较影响 dive_val
$ b


  • 影响



    $ ref 是对散列的引用。

     预循环:$ ref引用%散列
    循环传递0之后:$ ref引用%{$ hash {$ key [0]}}
    循环传递1:$ ref引用%{$ hash {$ key [0]} {$ key [1]}}
    Post循环使用:$ ref- > {$ key [2]}


  • dive_val



    $ p 是对标量的引用。

     预循环:$ p引用$ hash 
    循环传递0之后:$ p引用$ hash-> {$ key [0]}
    循环传递1之后:$ p引用$ hash-> {$ key [0]} {$ key [1]}
    循环传递2之后:$ p引用$ hash-> {$ key [0]} {$ key [1]} {$ key [2]}
    后循环使用:$$ p




dive_val 的方法是p
$ b


  • 在解除引用前不需要创建哈希(不像影响它在前面的循环中创建它)。
  • 实际上,标量根本不需要在哈希中。这意味着 dive_val 可以很容易地扩展以支持混合数组/哈希结构。
  • 没有必要专门处理根目录(如果你希望接受可能未定义的参数)。

  • 不需要特别处理最后一个键。

I am looking for a more effective way to write this affect subroutine in :

#!/usr/bin/perl
use 5.010;
use strict;

my @keys = qw/foo bar baz/;
my %hash = ( foo => {babel => 'fish'} );

affect (\%hash, 42);

sub affect {
   my $ref = shift;
   $ref = $ref->{$keys[$_]} //= {} for (0.. $#keys - 1);
   $ref->{$keys[$#keys]} = shift;
}

use Data::Dumper;
print Dumper \%hash;

And the expected result:

$VAR1 = {
          'foo' => {
                     'bar' => {
                                'baz' => 42
                              },
                     'babel' => 'fish'
                   }
        };

I was thinking about things like this, but obviously it can't work like this:

%hash{ @keys } = 42;

Any idea?

解决方案

it would be more effective if you actually passed the keys to it! Let's make it an lvalue sub at the same time.

sub dive_val :lvalue {
   my $p = \shift;
   $p = \( $$p->{$_} ) for @_;
   $$p
}

my %hash;
dive_val(\%hash, qw( foo babel )) = 'fish';
dive_val(\%hash, @keys) = 42;

There are two added advantages to this implementation.

First, you can use it to peek into the data structure.

print(dive_val($hash, @keys), "\n");

Second, it will autovivify its first argument.

my $hash;
dive_val($hash, @keys) = 42;

This function already exists as Data::Diver's DiveVal.

use Dive::Val qw( DiveVal );

DiveVal(\%hash, map \$_, @keys) = 42;


Comparison of the flow of affect and dive_val:

  • affect

    $ref is a reference to a hash.

    Pre-loop:            $ref references %hash
    After loop pass 0:   $ref references %{ $hash{$key[0]} }
    After loop pass 1:   $ref references %{ $hash{$key[0]}{$key[1]} }
    Post loop uses:      $ref->{$key[2]}
    

  • dive_val

    $p is a reference to a scalar.

    Pre-loop:            $p references $hash
    After loop pass 0:   $p references $hash->{$key[0]}
    After loop pass 1:   $p references $hash->{$key[0]}{$key[1]}
    After loop pass 2:   $p references $hash->{$key[0]}{$key[1]}{$key[2]}
    Post loop uses:      $$p
    

dive_val's approach is purer.

  • There's no need to create the hash before it's dereferenced (unlike affect which creates it in the previous loop pass).
  • In fact, the scalar doesn't need to be in a hash at all. This means dive_val could easily be extended to support mixed array/hash structures.
  • There's no need to treat the root specially (if you want to accept a potentially undefined argument).
  • There's no need to treat the last key specially.

这篇关于在一条指令中将值影响到多级哈希的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆