2

I have a question I'm hoping you could help with as I am new to hashes and hash reference stuff?

I have the following data structure:

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

If I want to access all the URLs in the key 'difference' so I can then perform some other actions on the URLs, what is the correct or preferred method of accessing those elements?

e.g I will end up with the following URLs that I can then do stuff to in a foreach loop with:

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

------EDIT------

Code to access the elements further down the data structure shown above:

my @urls;
foreach my $key1 ( keys( %{$VAR1} ) ) {
    print( "$key1\n" );
    foreach my $key2 ( keys( %{$VAR1->{$key1}} ) ) {
        print( "\t$key2\n" );
    foreach my $key3 ( keys( %{$VAR1->{$key1}{$key2}} ) ) {
        print( "\t\t$key3\n" );
    push @urls, keys %{$VAR1->{$key1}{$key2}{$key3}};
    }
  }
}
print "@urls\n";

Using the code above why do I get the following error?

Can't use string ("13238") as a HASH ref while "strict refs" in use at ....

darch
  • 4,200
  • 1
  • 20
  • 23
yonetpkbji
  • 1,019
  • 2
  • 21
  • 35

1 Answers1

7

It is not difficult, just take the second level of keys off every key in the variable:

my @urls;
for my $key (keys %$VAR1) {
    push @urls, keys %{$VAR1->{$key}{'difference'}};
}

If you're struggling with dereferencing, just keep in mind that all values in a hash or array can only be a scalar value. In a multilevel hash or array the levels are just single hashes/arrays stacked on top of each other.

For example, you could do:

for my $value (values %$VAR1) {
    push @urls, keys %{$value->{'difference'}};
}

Or

for my $name (keys %$VAR1) {
    my $site = $VAR1->{$name};
    push @urls, keys %{$site->{'difference'}};
}

..taking the route either directly over the value (a reference to a hash) or over a temporary variable, representing the value via the key. There is more to read in perldoc perldata.

TLP
  • 66,756
  • 10
  • 92
  • 149
  • thanks that exactly what I was looking for. What would the code look like if i wanted to only access the numbers at the end of every stackoverflow url i.e `13015`, `10506` and `33362`. I need to learn how to access different parts of the data structure , thanks for your help. – yonetpkbji Feb 20 '13 at 13:20
  • Could you show me what the code would ook like if i wanted to only access the numbers at the end of every stackoverflow url i.e 13015, 10506 and 33362. thanks a lot – yonetpkbji Feb 20 '13 at 13:39
  • 1
    @perl-user Its simple. The value of the key `'http://www.stackoverflow.com/'` is a hash ref. The keys in that hash ref is `'difference'` and `'equal'`, and their values are also hash refs. The values of those hash refs are the values you are after. Just stack the `for` loops that way and you'll be fine. Check your results with `Data::Dumper` if you are unsure what's going on. – TLP Feb 20 '13 at 13:56
  • Could you take a look at the edit ive added to my question please. Is this how the foreach loops should be done like you mentioned? and also why do I get the error message? thank you very much, you have helped a lot – yonetpkbji Feb 20 '13 at 15:26
  • 1
    @perl-user Well, the innermost values are no longer hash references, so you cannot use them as such. You just use the value as it is. By the way, you can make things easier on your eyes if you each loop assign a temporary variable for the particular step in the structure. E.g. `for my $key (keys %$VAR1) { my $href1 = $VAR1->{$key}; for my $key2 (keys %$href1) ...` – TLP Feb 20 '13 at 15:53
  • How would i use the values in the inner most loop then? Could you edit my foreach code in my question to explain what you mean above assigning a temporary variable, thankyou very much for your help. – yonetpkbji Feb 20 '13 at 15:57
  • @perl-user Just use the value, don't dereference it and use `keys` on it. What I mean with temporary variable is exactly what I wrote in the comment. `$href1` is the temporary variable. You have to try these things out for yourself. If you want me to write the entire code for you, I'm going to have to send you a bill. – TLP Feb 20 '13 at 16:26