Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Get hash values in multidimensional array to populate Term document matrix

by lobs (Acolyte)
on Feb 24, 2017 at 19:42 UTC ( [id://1182753]=perlquestion: print w/replies, xml ) Need Help??

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

I have an issue with accessing hash values within 2 arrays. The way the hash is stored in the arrays is as follows:
my @arr; my @subArr; my %hash = (); my %hash2 = (); $hash{key} = 12; $hash{pl} = 1; $hash{lop} = 9; $hash2{key} = 12; $hash4{pl} = 1; $hash8{lo} = 9; push(@subArr, \%hash); push(@subArr, \%hash2); push(@arr, \@subArr);
I'm not sure how to get the value of each key in the hashes. I keep on getting the reference to memory or 1/8. This is my code:
for my $i (0 .. $#arr){ $subd = $arr[i]; print"subLen: ".$subd."\n"; for my $j ( {{$arr[i]}} ) { foreach my $key{ keys %{$j}}{ print $key.": ".${$j}}{$key}; } { } }
EDIT: The solution in the comments worked but I tried to implement it in my program that is trying to get a term document matrix happens to get only one hash and print out values for that hash. I get the hash function by going through an array and adding the terms to the hash as follows (hash %termFreq is specific for the document and hash %docTerms is the features of all documents):
while ($element = shift(@numOfWordArr)) { $termsFreq{$element} ++; if(!exists($docTerms{$element})) { $docTerms{$element}++; } }
Then add the hash into an array of documents as follows:
push(@docArray, \%termsFreq);
Finally pass the array into an array to seperate the classes of the documents:
push(@classArr, \@docArray);
took the advice from this thread and did as follows to print the doc matrix to a csv file:
for my $i($#classArr) { print "subArr_ref: ".@{$classArr[$i]}."\n"; for my $hashRef(@{$classArr[$i]}) { print "hashRef: ".$hashRef."\n"; for my $key (sort keys %$hashRef) { print $csv $key."-- ".$hashRef->{$key}.","; } # foreach my $feat(@featureVector) { # print $csv $hashRef->{$feat}.","; # } print $csv $i."\n"; } }
As stated above I get rows of the same value since it is accessing the same hash per iteration. Help is much appreciated. Thanks!

Replies are listed 'Best First'.
Re: Get hash values in multidimensional array
by BillKSmith (Monsignor) on Feb 24, 2017 at 20:43 UTC
    Your dereferencing is much easier if your outer loop loops through the array rather than the indexes and the inner loop uses the function 'each' to get extract both key and value.
    use strict; use warnings; my @arr = ([ {key=>12, pl=>1, lop=>9}, {key=>12, pl=>1, lo =>9}, ]); foreach my $subArr_ref (@arr) { foreach my $hash_ref (@$subArr_ref) { while (my ($key, $value) = each %$hash_ref) { print "$key: $value\n"; } } } OUTPUT: pl: 1 lop: 9 key: 12 lo: 0 key: 12 pl: 1
    Bill
Re: Get hash values in multidimensional array
by poj (Abbot) on Feb 24, 2017 at 20:25 UTC

    You may find changing $j to $hr so you know it's a hashref makes things a bit clearer.

    #!perl use strict; use Data::Dumper; my %hash = ( key => 12, pl => 1, lop => 9 ); my %hash2 = ( key => 12, pl => 1, lo => 9 ); my @arr = ( [\%hash,\%hash2] ); for my $i (0 .. $#arr){ my $subd = @{$arr[$i]}; print "subLen: $subd\n"; for my $hr (@{$arr[$i]}){ for my $key (keys %$hr){ print $key.": ".$hr->{$key}."\n"; } } }
    poj
Re: Get hash values in multidimensional array
by AnomalousMonk (Archbishop) on Feb 25, 2017 at 01:12 UTC
      loop through the outter loop and reference the hash with : <%-{-{-{-<
Re: Get hash values in multidimensional array
by 1nickt (Canon) on Feb 25, 2017 at 02:11 UTC

    Here are a couple of examples using while and each to loop through the data structure (requires Perl minimum version 5.12), and using map to transform the array into a list of the key values.

    (I used your data-building technique for consistency.)

    use strict; use warnings; use feature 'say'; use Data::Dumper; my @arr = get_data(); say "Data:"; while ( my ($n, $aref) = each @arr ) { say " Aref: " . ($n + 1); while ( my ( $n, $href ) = each @{ $aref } ) { say " Href: " . ($n + 1); while ( my ( $key, $val ) = each %{ $href } ) { say " $key: $val"; } } } say '~~~~~~~~~~~~~~'; my @vals = map { $_->{'myKey'} } map { @{ $_ } } @arr; say "Inner values:"; say Dumper \@vals; sub get_data { my @arr; my @subArr1; my @subArr2; my %hash1 = ( myKey => 1 ); my %hash2 = ( myKey => 2 ); my %hash3 = ( myKey => 3 ); my %hash4 = ( myKey => 4 ); push(@subArr1, \%hash1, \%hash2); push(@subArr2, \%hash3, \%hash4); push(@arr, \@subArr1, \@subArr2); return @arr; }
    Output:
    $ perl 1182753.pl Data: Aref: 1 Href: 1 myKey: 1 Href: 2 myKey: 2 Aref: 2 Href: 1 myKey: 3 Href: 2 myKey: 4 ~~~~~~~~~~~~~~ Inner values: $VAR1 = [ 1, 2, 3, 4 ];

    Hope this helps!


    The way forward always starts with a minimal test.
Re: Get hash values in multidimensional array
by Marshall (Canon) on Feb 25, 2017 at 01:32 UTC
    Before trying to print @arr, I think you should learn how print what you call @subArr.

    I changed the terminology a bit below. I called @subArr, @href_array, array of hash references.

    #!/usr/bin/perl use strict; use warnings; my @href_array; #array of ref's to hash my @arr; #an array of ref's to @href_array arrays my %hash = (); my %hash2 = (); my %hash4 = (); my %hash8 = (); $hash{key} = 12; $hash{pl} = 1; $hash{lop} = 9; $hash2{key} = 88; #changed this to be different #than $hash{key} = 12 $hash4{pl} = 1; $hash8{lo} = 9; push(@href_array, \%hash); #array of ref's to hash push(@href_array, \%hash2); #array of ref's to hash push(@href_array, \%hash4); #array of ref's to hash push(@href_array, \%hash8); #array of ref's to hash dump_hashref_array (@href_array); sub dump_hashref_array # dump_hashes(\%h1,\%h2,...,\%hn) { my @hrefs = @_; my $n_table =1; foreach my $href (@hrefs) { print "dumping hash table ", $n_table++,"\n"; foreach my $key (keys %$href) { print "$key=>$href->{$key}\n"; } print "\n"; #just a spacer line between hashes } } __END__ PRINTS: dumping hash table 1 key=>12 pl=>1 lop=>9 dumping hash table 2 key=>88 dumping hash table 3 pl=>1 dumping hash table 4 lo=>9
    Update: Note that push(@arr, \@href_array); would mean that @arr is an array of references to @href_array. This would add one more foreach() level to the code. I recommend study of the above before trying to add yet another level to the data structure.

    A bit off topic, but I see you are flummoxed by this "1/8" sometimes result? This is kind of a weird thing, but here is how it could happen. A reference to hash could also result from different code. Anyway this is how you could get the string "1/8":

    #!/usr/bin/perl use strict; use warnings; my %hash; $hash{anything} =1; my $hash_result = %hash; print "scalar value of a this hash = $hash_result\n"; __END__ PRINTS: scalar value of a this hash = 1/8 # scalar values of a hash is a string, like "1/8" # Means that 1 of 8 hash buckets is currently in use. # A Perl hash always starts with 8 hash buckets. # # Perl will double the number of hash buckets as it # sees fit. You have no control over that decision. # # Current versions of Perl have some randomization of # the keys -- a run with the exact same data may # result in a difference in # of keys used or total keys. # Of course the code above will always result in "1/8".
Re: Get hash values in multidimensional array
by Laurent_R (Canon) on Feb 24, 2017 at 20:15 UTC
    Hi,

    your @arr array has never been populated with anything. So:

    for my $i (0 .. $#arr){
    isn't going to loop on anything.

    I would suggest that you use the following pragmas:

    use strict; use warnings;
    as this will enable the compiler to point out at some of your probable mistakes.

    Update: Sorry I probably looked at it too quickly, I missed the last push line.

      your @arr array has never been populated with anything
      It is for me. When I run the 1st code snippet (no strictures), I see something in @arr:
      use Data::Dumper; print Dumper(\@arr); $VAR1 = [ [ { 'key' => 12, 'lop' => 9, 'pl' => 1 }, { 'key' => 12 } ] ];

      What happens when you run it? The 2nd snippet has compile errors for me.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1182753]
Approved by toolic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (3)
As of 2024-04-19 20:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found