【问题标题】:How can I replace values in a deeply nested but arbitrary data structure?如何替换深度嵌套但任意数据结构中的值?
【发布时间】:2019-03-21 03:58:32
【问题描述】:

我有一个任意的数据结构。这种形式通常是相似的,因为它由大约四级深的数组和散列组成,大约有两到六个我想更改的值。一个典型的例子:

$VAR1 = [
          undef,
          [
            {
              '0' => 'some string'
            }
          ],
          undef,
          [
            undef,
            {
              '1033' => 'another string '
            }
          ]
        ];

虽然我知道语法足以访问这两个值并在此特定示例(或任何其他示例)中更改它们,但从一种用法到下一种用法,这将以硬编码表达式失败的方式发生变化。

这个感觉应该是一个简单的递归运行的sub,但是一旦发现数据结构的元素是数组或者hash,不知道怎么把元素通过引用传递到下一个递归调用中以便可以以非临时方式对其进行修改。以下代码递归失败(尽管如果它不递归,它可以更改顶级数组中的浅值并且此更改会持续):

sub deep_nested_replace {
    my ($d, $string) = @_;

    if (ref($d) eq 'ARRAY') {
        for (my $i=0; $i<scalar @$d; $i++) {
            deep_nested_replace($d->[$i], $string);
        }
    }
    elsif (ref($d) eq 'HASH') {
        foreach my $k (keys %$d) {
            deep_nested_replace($d->{$k}, $string);
        }
    }
    elsif (defined $d) {
        $d = $string;
    }
}

我该如何进行这项工作?如果这是错误的方法,那么正确的方法是什么?

【问题讨论】:

  • 在函数的第一行中分配给$d,您正在复制该值。如果您直接分配给@_ 中的相应元素,它应该会影响调用者数据。
  • 谢谢@Sam。如果您想写一个快速的答案,很乐意选择它。

标签: perl


【解决方案1】:

带有函数参数的@_ 数组包含传递给函数的标量(或其他显式引用)的别名。对其进行修改影响调用者数据。与grepmap 中的$_ 相同。这是您有时需要注意的其他编程语言所带来的问题。

但是,通过将一个标量变量赋值给另一个,就像惯用的 my ($d, $string) = @_ 一样,标量值从一个变量复制到另一个变量。

如果您想影响传递给调用方函数的标量值,您可以直接使用@_ 数组及其元素。

sub deep_nested_replace {
    my ($d, $string) = @_;

    if (ref($d) eq 'ARRAY') {
        deep_nested_replace($_, $string) for @$d;
    }
    elsif (ref($d) eq 'HASH') {
        deep_nested_replace($_, $string) for values %$d;
    }
    elsif (defined $d) {
        $_[0] = $string;
    }
}

【讨论】:

  • 添加了对答案进行必要更改(和一些简化)的代码。希望你不要介意。
  • 我当然不会:)
猜你喜欢
  • 1970-01-01
  • 2021-04-20
  • 2019-08-31
  • 2013-07-02
  • 1970-01-01
  • 2015-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多