Search code examples
perlhashwww-mechanizehashref

Perl WWW:Mechanize Accessing data in a hash reference


I have a question I'm hoping you could help with?

This is the last part I need help with in understanding hash references

Code:

my $content_lengths; # this is at the top
foreach my $url ( # ... more stuff

# compare
if ( $mech->response->header('Content-Length') != $content_length ) {
  print "$child_url: different content length: $content_length vs "
    . $mech->response->header('Content-Length') . "!\n";

  # store the urls that are found to have different content
  # lengths to the base url only if the same url has not already been stored
  $content_lengths->{$url}->{'different'}->{$child_url} = $mech->response->header('Content-Length');

} elsif ( $mech->response->header('Content-Length') == $content_length ) {
  print "Content lengths are the same\n";

  # store the urls that are found to have the same content length as the base
  # url only if the same url has not already been stored
  $content_lengths->{$url}->{'equal'}->{$child_url} = $mech->response->header('Content-Length');
}

What it looked like using Data::Dumper

$VAR1 = {
      'http://www.superuser.com/' => {
                                       'difference' => {
                                                         'http://www.superuser.com/questions' => '10735',
                                                         'http://www.superuser.com/faq' => '13095'
                                                       },
                                       'equal' => {
                                                    'http://www.superuser.com/ ' => '20892'
                                                  }
                                     },
      'http://www.stackoverflow.com/' => {
                                           'difference' => {
                                                             'http://www.stackoverflow.com/faq' => '13015',
                                                             'http://www.stackoverflow.com/questions' => '10506'
                                                           },
                                           'equal' => {
                                                        'http://www.stackoverflow.com/ ' => '33362'
                                                      }
                                         }
    };

What I need help with:

I need help understanding the various ways of accessing the different parts in the hash reference and using them to do things, such as print them.

So for example how do I print all the $url from the hash reference (i.e from Data::Dumper that will be http://www.superuser.com/ and http://www.stackoverflow.com/)

and how do I print all the $child_url or a particular one/subset from $child_url and so on?

Your help with this is much appreciated,

thanks a lot


Solution

  • You can navigate your hashref thusly:

    $hashref->{key1}{key2}{keyN};
    

    For example, if you want the superuser equal branch:

    my $urlArrayref = $hashref->{'http://www.superuser.com/'}{'equal'};
    

    More to the point, to print the urls (first level key) of the hashref, you would do:

    foreach my $key ( keys( %{$hashref} ) ) {
        print( "key is '$key'\n" );
    }
    

    Then if you wanted the second level keys:

    foreach my $firstLevelKey ( keys( %{$hashref} ) ) {
        print( "first level key is '$firstLevelKey'\n" );
        foreach my $secondLevelKey ( keys( %{$hashref->{$firstLevelKey}} ) ) {
            print( "\tfirst level key is '$secondLevelKey'\n" );
        }
    }
    

    And so forth...

    ----- EDIT -----

    This is working sample code from your example above:

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    
    my $content_lengths = {
        'http://www.superuser.com/' => {
            'difference' => {
                'http://www.superuser.com/questions' => '10735',
                'http://www.superuser.com/faq' => '13095'
            },
            'equal' => {
                'http://www.superuser.com/ ' => '20892'
            }
        },
        'http://www.stackoverflow.com/' => {
            'difference' => {
                'http://www.stackoverflow.com/faq' => '13015',
                'http://www.stackoverflow.com/questions' => '10506'
            },
            'equal' => {
                'http://www.stackoverflow.com/ ' => '33362'
            }
        }
    };
    
    foreach my $key1 ( keys( %{$content_lengths} ) ) {
        print( "$key1\n" );
        foreach my $key2 ( keys( %{$content_lengths->{$key1}} ) ) {
            print( "\t$key2\n" );
            foreach my $key3 ( keys( %{$content_lengths->{$key1}{$key2}} ) ) {
                print( "\t\t$key3\n" );
            }
        }
    }
    

    Which results in this output:

    http://www.superuser.com/
            difference
                    http://www.superuser.com/questions
                    http://www.superuser.com/faq
            equal
                    http://www.superuser.com/
    http://www.stackoverflow.com/
            difference
                    http://www.stackoverflow.com/faq
                    http://www.stackoverflow.com/questions
            equal
                    http://www.stackoverflow.com/