Search code examples
perlperl-data-structureshash-reference

Perl nested data structures


I'm having trouble wrapping my brain around the data structure that is being returned...What I need to do is inspect the results, and modify a field if it is a HASH. Within 'results' any KEY that is a HASH with a KEY of 'null' and value of '1' needs to be changed to '0'. Below I have pasted some sample data from Data::Dumper of the return. In this instance, I want to change data in four different places. I have been dealing with this for some time and just can't figure it out....any help is appreciated.

$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'
    }
  ]
};

Solution

  • I didn't get exactly what you mean by "any KEY that is a HASH" - probably you mean: "any VALUE that is a HASH". Anyway, if I got it right, maybe this script might help. It will recursively check the hashes inside the data structure and change the values as needed.

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

    EDIT: setting the whole hash to 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);
                }
            }
        }
    }
    

    while not the best solution, it works.