Search code examples
arraysperlperl-data-structureshash

How do I iterate through a reference to an array of hashes in Perl?


I have a reference to an array of hases that I pass to a subroutine in my perl script

This is the code:

sub mySub {
    (my $resultref) = @_;
    my @list = @$resultref;
    print Dumper(@list);
    foreach my $result (@list) {
        print Dumper($result);
    }
}

And this is the output:

$VAR1 = [
          {
            'portName' => '1.1',
            'ips' => [
                       '192.168.1.242'
                     ],
            'switchIp' => '192.168.1.20',
            'macs' => [
                        '00:16:76:9e:63:47'
                      ]
          },
          {
            'portName' => '1.10',
            'ips' => [
                       '192.168.1.119',
                       '192.168.1.3'
                     ],
            'switchIp' => '192.168.1.20',
            'macs' => [
                        'd0:67:e5:f8:7e:7e',
                        'd0:67:e5:f8:7e:76'
                      ]
          },
        ];

$VAR1 = [
          {
            'portName' => '1.1',
            'ips' => [
                       '192.168.1.242'
                     ],
            'switchIp' => '192.168.1.20',
            'macs' => [
                        '00:16:76:9e:63:47'
                      ]
          },
          {
            'portName' => '1.10',
            'ips' => [
                       '192.168.1.119',
                       '192.168.1.3'
                     ],
            'switchIp' => '192.168.1.20',
            'macs' => [
                        'd0:67:e5:f8:7e:7e',
                        'd0:67:e5:f8:7e:76'
                      ]
          },
        ];

The loop is putting the whole array into the $result variable. I have tried dereferencing it as @$result[0] with no success.

How do I loop those hashes individually?

Thanks!


Solution

  • The arguments to Data::Dumper's Dumper function should be references. E.g.:

    use Data::Dumper;
    my @array = ([1,2,3], [11,22,33]); # Two-dimensional array
    print Dumper @array;               # print array
    print Dumper \@array;              # print reference to array
    

    The output:

    $VAR1 = [
              1,
              2,
              3
            ];
    $VAR2 = [
              11,
              22,
              33
            ];
    
    $VAR1 = [
              [
                1,
                2,
                3
              ],
              [
                11,
                22,
                33
              ]
            ];
    

    The second print gives us the entire structure in one variable. When you print the array directly, it expands into all its elements, so...

    print Dumper @array;
    

    Is equivalent to:

    print Dumper $array[0], $array[1], ..., $array[$#array];
    

    So, in your case, just do:

    sub mySub {
        my ($resultref) = @_;
        print Dumper $resultref;
    }
    

    Accessing the inner variables:

    Just take a look at Data::Dumper's output:

    $VAR1 = [    # bracket denotes start of an array ref
              {  # curly brackets = hash ref
                'portName' => '1.1',
                'ips' => [
                           '192.168.1.242'
                         ],
                'switchIp' => '192.168.1.20',
                'macs' => [
                            '00:16:76:9e:63:47'
                          ]
              }, # hash ref ends, comma = new array element begins
              {  # new hash ref 
                'portName' => '1.10',
                'ips' => [
                           '192.168.1.119',
                           '192.168.1.3'
                         ],
                'switchIp' => '192.168.1.20',
                'macs' => [
                            'd0:67:e5:f8:7e:7e',
                            'd0:67:e5:f8:7e:76'
                          ]
              }, # end of hash
            ];   # end of array
    

    Important to note here is that all elements of an array, and all the values of a hash are scalars. Therefore, all hashes and arrays can easily be broken up into a list of scalars.

    for my $aref (@$resultref) {  # starting array ref
        for my $aref2 (@$aref) {  # second level array ref
            for my $href (@$aref2)  # here begins the hash
                local $\ = "\n";    # add newline to print for simplicity
                print $href->{portName};    # printing a scalar
                print for @{$href_>{ips}};  # printing an array ref w post-script loop
                print $href->{switchIp};
                print for @{$href->{macs}};
            }
        }
    }
    

    Note the use of the arrow operator to dereference a reference. If you have a hash or array you would do $array[0] or $hash{$key}, but by using a reference, you "point" to the address contained in the reference instead: $array->[0] or $hash->{$key}.