如何替换深度嵌套但任意的数据结构中的值?

时间:2019-03-20 18:46:53

标签: perl

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

split.collect { it.replaceAll(/(.*)\/(.*).(java|class)/, '$1.$2')}

虽然我非常了解语法,可以访问这两个值并在此特定示例(或任何其他示例)中更改它们,但从一种用法到另一种用法,这将改变硬编码表达式失败的方式。

感觉它应该是一个递归运行的简单子,但是一旦发现数据结构的元素是数组或哈希,我不知道如何通过引用将元素传递到下一个递归调用中这样就可以以非临时方式对其进行修改。以下代码递归失败(尽管如果不递归,则可以更改顶级数组中的浅值,并且此更改会生效):

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

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

1 个答案:

答案 0 :(得分:3)

带有函数参数的@_数组包含传递给函数的标量(或其他显式引用)的别名。对它的修改 将影响呼叫者数据。与$_grep中的map相同。这是您有时需要小心的其他编程语言所带来的。

但是,通过将一个标量变量分配给另一个变量,如惯用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;
    }
}