1

我无法将我的大脑包裹在返回的数据结构周围......我需要做的是检查结果,如果它是一个 HASH 则修改一个字段。在“结果”中,任何作为 HASH 且 KEY 为“null”且值为“1”的 KEY 都需要更改为“0”。下面我粘贴了一些来自 Data::Dumper 的示例数据。在这种情况下,我想在四个不同的地方更改数据。我已经处理了一段时间,只是无法弄清楚....任何帮助表示赞赏。

$VAR1 = {
  'results' => [
    {
      'admin' => 'DUMMY DATA',
      'object' => 'DUMMY DATA',
      'ifDescr' => 'DUMMY DATA',
      'total_device' => {
        'null' => '1'
      },
      'ifIndex' => 'DUMMY DATA',
      'oper' => 'DUMMY DATA',
      'percent_online' => 'DUMMY DATA',
      'device_offline' => {
        'null' => '1'
      },
      'dataflow' => 'DUMMY DATA',
      'Map' => 'DUMMY DATA',
      'ifdevice' => 'DUMMY DATA',
      'device_online' => 'DUMMY DATA'
    },
    {
      'admin' => 'DUMMY DATA',
      'object' => 'DUMMY DATA',
      'ifDescr' => 'DUMMY DATA',
      'total_device' => {
        'null' => '1'
      },
      'ifIndex' => 'DUMMY DATA',
      'oper' => 'DUMMY DATA',
      'percent_online' => 'DUMMY DATA',
      'device_offline' => {
        'null' => '1'
      },
      'dataflow' => 'DUMMY DATA',
      'Map' => 'DUMMY DATA',
      'ifdevice' => 'DUMMY DATA',
      'device_online' => 'DUMMY DATA'
    }
  ]
};
4

3 回答 3

1

我无法将我的大脑包裹在返回的数据结构上......

您已经接受了答案,我只是要澄清对Data::Dumper输出的解释:

  • 每个都{...}意味着对 hash 的引用。您将看到key => value,哈希元素。
  • 每个[...]代表对数组的引用。您将看到value,数组元素。

分解你所拥有的:

$VAR = $VAR1 = {
   'results' => [
        ....       # This is an array reference
    ]

或 $VAR->{results} = [];

这是一个带有单个键的散列results。散列具有对数组的引用,因为它的值。至今:

$VAR1 = {
  'results' => [  # This is the [0] element in my array
    {
        ...       # This is a hash reference
    }
]
[                 # This is the [1] element in my array
    {
        ...       # This is a hash reference
    }

在这个数组中,有两个值,每个值都指向一个哈希引用:

$VAR->{results}->[0] = {};
$VAR->{results}->[1] = {};

在每个数组中,哈希引用都有 12 个键和值:

  • 行政
  • 数据流
  • 设备在线
  • 目的
  • 如果描述
  • ifDevice
  • 如果索引
  • 操作
  • 在线百分比
  • 地图
  • 这些都是有参考的......
    • total_devices
    • devices_offline

前 10 个只是键/值对。最后两个是对具有单个键/值对的进一步散列的引用。键为空。我认为这是某种错误。

现在我可以像这样引用这些项目之一:

$VAR->{results}->[1]->{ifIndex} = 'DUMMY DATA';

假设当前结构,这是一种在循环中引用它的方法:

my $VAR = some_function()                # Returns a reference to a hash.

for my $result ( keys %{ $VAR } ) {     # Dereference the hash reference...
   say "Key for results is '$result'";  # Only one result. And that's 'result'...
   my @array = $VAR->{$result};         # Dereference the array reference that hash points to
   for my $element ( 0..$#array ) {     # Now we get to the two elements in the array
      say qq(Looking at element #$element);
      my $hash_key = $array[$element];  # he hash reference that the array points to
      my %inner_hash = %{ $hash_key };  # Another dereference...
      for my $key ( keys %inner_hash" ) {
        say "\$VAR->{$result}->[$element]->{%hash_key} = "
           . $VAR->{$result}->[$element]->{%hash_key};
      }
   }
}

这不会完全起作用,因为total_device并且device_offline再次是哈希引用。我应该在最里面的循环中做一个例外,如果其中任何一个是我的内部哈希的关键,我需要再次取消引用以获取哈希。我会让你解决这个问题。

当然,我知道我的结构,所以我可以编写一个程序结构来处理它。如果我不知道我的数据结构的布局,我将不得不使用该ref命令来确定我指的是哈希还是数组,并相应地取消引用和循环。这几乎是什么Data::Dumper

我通常假设这样一个复杂的结构来自构造函数,并且我希望在这样的 Data::Dumper 转储中看到对象的祝福类名称。在这种情况下,我会告诉您使用该类的方法,而不是解构数据结构并自行处理。这是面向对象设计中的禁忌。

您应该始终将数据结构视为一个黑盒子。您不应该仅仅因为 Perl 不提供用于将结构和方法标记为private的遮蔽物而通过窗口达到峰值。还是不礼貌。

但是,Data::Dumper 没有显示类的名称,因此它不是类对象。看看数据结构。

查看Perl 参考教程,看看它是否有助于为您澄清情况。

于 2014-03-21T14:27:39.267 回答
0

我没有完全理解“任何作为 HASH 的 KEY”的意思——可能你的意思是:“任何作为 HASH 的 VALUE”。无论如何,如果我做对了,也许这个脚本可能会有所帮助。它将递归地检查数据结构内的哈希值并根据需要更改值。

#!/usr/bin/env perl
use strict;
use warnings;

use Data::Dumper;

# test data given in the post
my $VAR1 = {...}; # truncated

sub recursive_change {
    my $hash = shift;
    foreach my $key (keys %{$hash}) {
        my $value = $hash->{$key};
        if ($key eq 'null' && $value eq '1') { # or 1, depends
            $hash->{$key} = '0'; # or 0, depends
        }
        elsif (ref($value) eq 'HASH') {
            recursive_change($value);
        }
    }
}


foreach my $elem (@{$VAR1->{results}}) {
    recursive_change($elem);
}

print Data::Dumper->new([ $VAR1 ],[ '*VAR1' ])->Sortkeys(1)->Dump();

编辑:将整个哈希设置为 0:

sub recursive_change {
    my $hash = shift;
    foreach my $key (keys %{$hash}) {
        my $value = $hash->{$key};
        if (ref($value) eq 'HASH') {
            if ($value->{null} eq '1') {
                $hash->{$key} = 0;
            }
            else {
                change($value);
            }
        }
    }
}

虽然不是最好的解决方案,但它确实有效。

于 2014-03-20T20:19:37.987 回答
0

听起来您需要遍历结果的元素,并且对于它们中的每一个,如果任何值是 hashref,并且该 hashref 具有键值对 null => 1,则将其替换为 null => 0。

这应该看起来像:

# iterate through results
for my $result (@$results) {
    # check each hash in results for nested hashes
    for my $key (keys(%$result)) {
        # if the value here is a hashref, do stuff
        if(ref $result->{$key} eq 'HASH') {
            # the stuff to be done 
            # specifically, replace null => 1 with null => 0
            $result->{$key}->{null} = 0 if $result->{$key}->{null} == 1;
        }
    }
}

当我测试它时,它似乎做了你想要的(用 null=>0 替换 4 个 null=>1 实例)。我敢肯定有一个更漂亮的方式来写这个。

于 2014-03-20T20:26:26.947 回答