in reply to A hash of an array containing hashes & arrays

Couple things... First, you don't want to use eq when checking the result of your ref() call, because it'll never match. The ref($item) will return a value like HASH(0x8580988), so you only want to see if it contains the string "HASH". Like so...
if (ref($item) =~ /HASH/) {}
Second, if you're trying to print out the actual values in the hash or array referenced in your top-level array, you're going to need to dereference them.
print "Array in Array: ", @{$item}, "\n"; ... print "Hash in Array: ", %{$item}, "\n";
...and so you end up with something like...
#!/usr/bin/perl -w use strict; $, = " "; my %Volume_Info = ( alpha => [ 0, 512, 1048576, 1, { one => 'first_hash' }, [ 'two', 'first_array' ], { three => 'second_hash' }, -1, 0, 0, 0, 0, 0, 'zfod', 0 ], beta => [ 1, 2, 3, { four => 'third_hash' }, 2, 1 ] ); for my $vol_key ( sort keys %Volume_Info ) { print "\nVolume: $vol_key\n"; foreach my $item ( @{ $Volume_Info{$vol_key}} ) { if (ref($item) =~ /ARRAY/) { print "Array in Array item: ", @{$item}, "\n"; } elsif (ref($item) =~ /HASH/) { print "Hash in Array: ", %{$item}, "\n"; } else { print "Array Item: $item \n"; } } }
...which produces...
Volume: alpha Array Item: 0 Array Item: 512 Array Item: 1048576 Array Item: 1 Hash in Array: one first_hash Array in Array item: two first_array Hash in Array: three second_hash Array Item: -1 Array Item: 0 Array Item: 0 Array Item: 0 Array Item: 0 Array Item: 0 Array Item: zfod Array Item: 0 Volume: beta Array Item: 1 Array Item: 2 Array Item: 3 Hash in Array: four third_hash Array Item: 2 Array Item: 1
Hope this helps.

-Bird

Update: Made my code a little more consistent across examples.

Update 2: Silly me not reading up on ref before responding. :-} See comments by thelenm and Chmrr below.

Replies are listed 'Best First'.
Re: Re: A hash of an array containing hashes & arrays
by ebodine (Novice) on Aug 21, 2002 at 18:08 UTC
    I questioned the "ref($item) eq " as well. But take a look at the ref function description in the Camel Book 3rd Ed. on pg. 773. It uses "eq" as well. I tried @{$item} & %{$item} and got the following:

    Volume: alpha
    Array Item: 0
    Array Item: 512
    Array Item: 1048576
    Array Item: 1
    Hash in Array: %{HASH(0x8580a24)}
    Array in Array item: ARRAY(0x840824c)
    Hash in Array: %{HASH(0x8580f4c)}
    Array Item: -1
    Array Item: 0
    Array Item: 0
    Array Item: 0
    Array Item: 0
    Array Item: 0
    Array Item: zfod
    Array Item: 0
    Array Item:

    --ERick
      You can test ref using eq. Try this, for example:
      perl -le '$foo{"bar"} = ["a","b"]; print ref $foo{"bar"}'
      ... prints "ARRAY". But if for some reason you're testing the stringification of an array reference (not the return value of ref), then you shouldn't use eq.

      What are you expecting to see in your output? Hashes are not interpolated into strings, but arrays are, so printing "Array in Array item: @$item" should print the array elements in $item. A clearer way would be a foreach loop or map, perhaps like this:

      if (ref $item eq 'ARRAY') { print "Array in Array item:\n"; foreach (@$item) { print " $_\n"; } } elsif (ref $item eq 'HASH') { print "Hash in Array item:\n"; foreach (keys %$item) { print " $_ -> $item->{$_}\n"; } } else { print "Array Item: $item\n"; }

      -- Mike

      --
      just,my${.02}

        The following is what I ended up doing. Part of the problem here was that I didn't know exactly what the data was (maintaining someone else's 12k lines of perl w/ almost no comments is a b****) and I still don't know where some of it is coming from. Any suggestions for improvement would be appreciated.

        The data was arranged:
        %::Volume_Info = { 0, 512, 1048576, 1, %spindles = { 0 => ARRAY 1 => ARRAY 2 => ARRAY 3 => ARRAY }, [ ARRAY ], %copy_pool = { 0 => [ ARRAY, 0, 0, 1] }, -1, 0, 0, 0, }
        for my $vol_key ( keys %::Volume_Info ) { print "Volume " . ref($::Volume_Info{$vol_key}) . "\n"; foreach my $item ( $::Volume_Info{$vol_key} ) { if (ref($item) eq "ARRAY") { foreach my $item2 (@$item) { if (ref($item2) eq "ARRAY") { foreach my $ar_el (@$item2) { print "array_element: @$ar_el\n"; } } elsif (ref($item2) eq "HASH") { foreach my $hash_key (keys %$item2){ print "\t hash key: $hash_key\n"; if (ref($$item2{$hash_key}) eq "ARRAY") { foreach my $item3 ($$item2{$hash_key}) + { # if (ref($item3) eq "ARRAY") { # foreach my $an_el (@$item3) { # print "\t\t\tanother elem +ent @$an_el\n"; # } # } else { print "\t\tspindle values: @$i +tem3\n"; #} } } } } else { print "Array Item: $item2 \n"; } } } } }
Re: Re: A hash of an array containing hashes & arrays
by Chmrr (Vicar) on Aug 21, 2002 at 18:54 UTC

    Your comment about ref is not quite correct. If used on a blessed object, it will return the package the object has been blessed into. Otherwise, it will simply return one of the built-in types as strings, that is, one of qw/SCALAR ARRAY HASH CODE REF GLOB LVALUE/ Thus, use of eq in this case is actually correct. See perldoc -f ref for more information.

    perl -pe '"I lo*`+$^X$\"$]!$/"=~m%(.*)%s;$_=$1;y^`+*^e v^#$&V"+@( NO CARRIER'