【问题标题】:Accessing and modifying a nested hash based on a dot separated string基于点分隔字符串访问和修改嵌套哈希
【发布时间】:2023-03-12 16:46:02
【问题描述】:

我有一个字符串作为输入,比如 apple.mango.orange = 100

我还有一个哈希参考:

$inst = { '香蕉' => 2, '番石榴' => 3, '苹果' => { '芒果' => { '橙色' => 80 } } };

我想使用输入字符串修改橙色的值。有人可以帮助我如何做到这一点吗?

我尝试将字符串拆分为 (key, value) 对。然后我对密钥字符串执行了以下操作:

my $key2 = "\$inst->{".$key."}";
$key2 =~ s/\./}->{/g;
$$key2 = $value;

这不能按预期工作。有人可以帮我吗?我已阅读有关不使用变量值作为变量的 Perl 常见问题解答,但我想不出替代方案。

【问题讨论】:

    标签: perl variables strict


    【解决方案1】:

    您正在构建由(错误)Perl 代码组成的字符串,但您从未要求 Perl 执行它。 ...但这不是正确的方法。

    sub dive_val :lvalue {
       my $p = \shift;
       $p = \($$p->{$_}) for @_;
       $$p
    }
    
    my @key = split /\./, "apple.mango.orange";
    dive_val($inst, @key) = $value;
    

    use Data::Diver qw( DiveVal );
    
    my @key = split /\./, "apple.mango.orange";
    DiveVal($inst, map \$_, @key) = $value;
    

    【讨论】:

      【解决方案2】:

      在这里,符号引用不仅是一个非常糟糕的主意,它甚至不能解决您的问题。你正在$key2 中构建一个表达式,仅仅在它的名字前面加上另一个美元符号不会让perl 执行那个代码。为此,您需要eval,这是另一个坏主意

      您可以安装和使用 Data::Diver 模块,它正是这样做的,或者您可以简单地遍历哈希键列表,每次都选择一个新的哈希引用并将值分配给元素最后一个键

      最大的问题实际上是将传入的字符串解析为键和值的列表。此代码实现了一个子例程apply,它将字符串中的隐含操作应用于嵌套散列。除非您对自己的数据有信心,否则需要添加一些错误检查以确保列表中的每个键都存在。 Data:;Dumper 的输出只是为了证明结果的有效性

      use strict;
      use warnings 'all';
      
      use Data::Dumper;
      
      my $inst = { 'banana' => 2, 'guava' => 3, 'apple' => { 'mango' => { 'orange' => 80 } } };
      
      my $s = 'apple.mango.orange = 100';
      
      apply($s, $inst);
      
      print Dumper $inst;
      
      sub apply {
          my ($operation, $data) = @_;
          my ($keys, $val) = $operation =~ /([\w.]+)\s*=\s*(\d+)/;
      
          my @keys = split /\./, $keys;
          my $last = pop @keys;
      
          my $hash = $data;
          $hash = $hash->{$_} for @keys;
          $hash->{$last} = $val;
      }
      

      输出

      $VAR1 = {
                'banana' => 2,
                'apple' => {
                             'mango' => {
                                          'orange' => '100'
                                        }
                           },
                'guava' => 3
              };
      

      【讨论】:

        猜你喜欢
        • 2011-02-11
        • 2010-09-24
        • 2011-10-31
        • 1970-01-01
        • 2014-01-29
        • 2012-01-23
        • 2016-12-31
        • 1970-01-01
        相关资源
        最近更新 更多