chinamox has asked for the wisdom of the Perl Monks concerning the following question:

Hello monks,

Working to finish up an assignment tonight and I have gotten stuck on trying to convert an HoH to an array. I am attempting to extract an @array from the following data structure:

$hash{$w1}{$w2} = { total_counts => $tot_counts, words => { $nw => $count, } }

Basically I want to import all the keys from HoH 'words' (possibly using several '$nw's as keys) into and @array $count times each. I will then use the array function 'rand()' to randomly retrieve and print the content of one of @array's elements.

I have tried to uses the following code, with no sucess:

@newarray = $hash{ $w1 }->{ $w2 }->{ words };

I know that was kind of a stab in the dark, but I am having problems figuring out how to extract each individual value of $nw and use it as a key which is then pushed into an array $count times. My thanks and gratitude to anyone who can show me the way to accomplish this.

-mox

Replies are listed 'Best First'.
Re: importing all the values stored in an HoH into an array
by bart (Canon) on Oct 31, 2006 at 11:58 UTC
    @newarray = $hash{ $w1 }->{ $w2 }->{ words };
    Be aware that after initializing your hash as you did, this will return a hash ref. You can pull out the data like this:
    $hashref = $hash{ $w1 }->{ $w2 }->{ words }; foreach my $k (keys %$hashref) { print " * $k: $hashref->{$k}\n"; }
    as an example.

    Perhaps if you want an array, perhaps all you want is the keys?

Re: importing all the values stored in an HoH into an array
by BrowserUk (Patriarch) on Oct 31, 2006 at 12:04 UTC

    Updated: Added the omitted { words } term in the keys expression.

    Update2: Added omitted paren as noted by johngg.

    What you appear to be asking for is

    my @wordsList; for my $word ( keys %{ $hash{ $w1 }{ $w2 }{ words } } ) { push @wordsList, ( $key ) x $hash{ $w1 }{ $w2 }{ words }{ $key }; } print @wordsList[ rand( @wordsList ) ];

    There are probably bits of that you do not understand, but rather than my trying to guess which they are, it's easier if you ask. In this thread rather than starting a new one.

    Note: I've omitted the -> between the terms of the hash references as they are optional and I personal don't think thay add clarity, but your way is fine also.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      I think you might have a typo in your

      print @wordsList[ rand( @wordsList ];

      perhaps you wanted

      print @wordsList[ rand @wordsList ];

      Cheers,

      JohnGG

      This worked like a charm, Thanks!

      Better yet, I think I can make some sense out of how the references work.

      one question: In the line:

      for my $word ( keys %{ $hash{ $w1 }{ $w2 }{ words } } ) {

      What does 'keys' stand for? Is it a reference?

      Thank you very much for your help!

      -mox
        keys is a function for pulling out all the keys from a hash. There is also a values function for ... er ... pulling out the values. You should also be aware of each. Here is an example.

        use strict; use warnings; my %dets = ( name => q{fred}, age => 33); while (my ($key, $value) = each %dets) { # Do something with key and value here }

        Note that you can't predict the order in which these functions will present keys, values or key/value pairs.

        I hope this is of use.

        Cheers,

        JohnGG

        What does 'keys' stand for? Is it a reference?

        'keys' is a Perl built-in function. It returns a list of the keys in a given hash. You should read the documentation (which I already pointed you to above).

        --
        <http://dave.org.uk>

        "The first rule of Perl club is you do not talk about Perl club."
        -- Chip Salzenberg

Re: importing all the values stored in an HoH into an array
by davorg (Chancellor) on Oct 31, 2006 at 11:59 UTC

    So, in $hash{ $w1 }->{ $w2 }->{ words } (which can be written more concisely without the unnecessary arrows - $hash{ $w1 }{ $w2 }{ words }) you have a reference to a hash. And you want to get all of the keys from that hash. So use the keys function. Only slight complexity is that 'keys' takes a hash as a parameter, not a hash reference. So you need to dereference your reference.

    @newarray = keys %{ $hash{ $w1 }{ $w2 }{ words } };

    Update: s/values/keys/g

    Update: On re-reading your question, I think that BrowserUk has understood it better than me.

    Update: Fixed doc link.

    --
    <http://dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

Re: importing all the values stored in an HoH into an array
by cankara (Initiate) on Oct 31, 2006 at 12:35 UTC
    This might seem extensive but the recursion will fetch you all elements within any given HOH into a single array structure. Not sure if this is exactly your requirement..
    
    $hash =
        {
            total_counts => tot_counts,
            words => {
                           nw => 1,
                     }
        };
    
    @finalarray = get_array($hash);
    print "@finalarray";
    
    sub get_array {
        my($hash) = @_;
        my $array = [];
        if(ref $hash eq 'HASH') {
            foreach (keys %$hash) {
                if(ref $hash->{$_} eq 'HASH') {
                    push @{$array} , $_;
                    push @{$array} , get_array($hash->{$_});
                }
                else {
                    push @{$array} , $_;
                    push @{$array} , $hash->{$_};
                }
            }
        }
        return @$array;
    }
    

      Thank you very much for the powerful bit of code. It didn't quite work for this problem, but I will certainly stick it in my pocket and use it in the future! Do you keep a library of handy code or did you just spin this off just now? In either case, Thank you very much for your time and efforts.

      -mox
Re: importing all the values stored in an HoH into an array
by themage (Friar) on Oct 31, 2006 at 12:08 UTC
    hi chinamox,

    I think you need more or less this:

    my @array=(); for my $word (keys %{$has{$w1}->{$w2}}) { push @array, ($word) x $hash{$w1}->{$w2}->{$word}; }


      Thank you for your help. I ended up using something very similar to your example.

      cheers

      -mox