簡體   English   中英

Perl嵌套數據結構

[英]Perl nested data structures

我在將大腦包裹在返回的數據結構上時遇到麻煩...我需要做的是檢查結果,如果是HASH則修改字段。 在“結果”中,需要將任何具有KEY為“ null”且值為“ 1”的HASH的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'
    }
  ]
};

我在將大腦包裹在要返回的數據結構上時遇到麻煩...

您已經接受了答案,我只是要澄清對Data::Dumper輸出的解釋:

  • 每個{...}表示對哈希的引用 您將看到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個鍵和值:

  • 管理
  • 數據流
  • devices_online
  • 賓語
  • ifDescr
  • ifDevice
  • 的ifIndex
  • OPER
  • percent_online
  • 地圖
  • 這些都是參考。
    • 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_devicedevice_offline再次是哈希引用。 我應該在我的最內層循環中例外,並且如果其中任何一個是我的內在散列的關鍵,我都需要進行另一次取消引用才能到達散列。 我會讓你解決。

當然,我知道我的結構,因此我可以編寫一個程序結構來處理它。 如果我不知道數據結構的布局,則必須使用ref命令來確定我是在引用哈希還是數組,並相應地取消引用和循環。 這幾乎就是Data::Dumper所做的。

我通常認為這樣的復雜結構來自構造函數,並且我希望在這樣的Data :: Dumper轉儲中看到對象的受祝福的類名。 在這種情況下,我會告訴您使用該類的方法,而不要解構數據結構並自行修改。 在面向對象的設計中這是不行的。

您應該始終將數據結構視為黑匣子。 您不應該僅僅因為Perl沒有提供盲目性來將結構和方法標記為私有而在窗口中達到頂峰。 舉止仍然很糟糕。

但是,Data :: Dumper沒有顯示類的名稱,因此它不是類對象。 忘掉數據結構。

查看《 Perl參考指南》,以了解是否有助於您解決這種情況。

我並沒有完全理解“散列的任何鍵”的含義-可能是您的意思:“散列的任何值”。 無論如何,如果我做對了,也許這個腳本可能會有所幫助。 它將遞歸檢查數據結構中的哈希並根據需要更改值。

#!/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);
            }
        }
    }
}

雖然不是最好的解決方案,但它可以工作。

聽起來您需要遍歷結果的元素,對於每個元素,如果任何值都是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實例)。 我敢肯定有一種寫得更好的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM