PDA

View Full Version : Making a hash of hash of arrays


naqvia
05-27-2008, 09:08 PM
How do I do this? I have something like this:

push @{$sequencing_results{$result->query_name}{$type}}, $hsp->start('query'),$hsp->end('query'),$hit->name,$hsp->start('hit'),$hsp->end('hit'),$hsp->length('hit')."of".$type_length{$type},$result->database_letters,$hsp->percent_identity,$hsp->expect,$hsp->query_string;

But obviously this it not working...

FishMonger
05-27-2008, 09:29 PM
How do I do this? I have something like this:

push @{$sequencing_results{$result->query_name}{$type}}, $hsp->start('query'),$hsp->end('query'),$hit->name,$hsp->start('hit'),$hsp->end('hit'),$hsp->length('hit')."of".$type_length{$type},$result->database_letters,$hsp->percent_identity,$hsp->expect,$hsp->query_string;

But obviously this it not working...

No, it is not obvious that it's not working. You need to tell us what you expected and how the results of your push assignment differ from what you expected.

Here's a simplified version which produces the HoHoA structure that I'd expect.
#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

my %HoHoA;

push @{$HoHoA{'level 1'}{'level 2'}}, 1,2,3,4,5;
print Dumper \%HoHoA;

D:\>HoHoA.pl
$VAR1 = {
'level 1' => {
'level 2' => [
1,
2,
3,
4,
5
]
}
};

How does that differ from what you expected?

naqvia
05-27-2008, 09:52 PM
I want to do exactly what your example shows but I want to iterate through the array using a foreach loop.

FishMonger
05-27-2008, 10:21 PM
Does this help?

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

my %HoHoA;

push @{$HoHoA{'level 1'}{'numbers'}}, 1,2,3,4,5;
push @{$HoHoA{'level 1'}{'letters'}}, qw/a b c d e/;

foreach my $key ( keys %{$HoHoA{'level 1'}} ) {
print "$key\n";
foreach my $array_element ( @{$HoHoA{'level 1'}{$key}} ) {
print "\t$array_element\n";
}
}

D:\>HoHoA.pl
letters
a
b
c
d
e
numbers
1
2
3
4
5

naqvia
05-27-2008, 11:09 PM
Almost. I want something like this:


foreach my $key ( keys %HoHoA ) {
print "$key\n";
foreach my $array_element ( @{$HoHoA{'$key'}{$key}[0]} ) {
print $HoHoA{$key}[0],"\t$array_element\n";
}
}


The first value of the %HoHoA is an array, right? So I want to iterate through it like I have tried, but for some reason it is not working out for me.

FishMonger
05-28-2008, 02:34 AM
The first value of the %HoHoA is an array, right?No, the first value(s) of your outer foreach loop will be the name(s) of the top level hash key(s).

The example that I posted has only 1 top level key, which is named 'level 1' but has 2 second level keys under that 1 top level key, which are 'numbers' and 'letters'.

'$key' in your hash dereferencing won't work because the single quotes is preventing variable interpolation, which means your using the literal sting '$key' as the hash key instead of the value of the $key variable. Your second problem in that inner loop is that you're using the top level $key value in the second level key position, i.e., you're using 'level 1' instead of 'numbers' or 'letters' as the second level key.

There are 1 or 2 other problems that I could point out, but it might be easier if I post another example. Based on your dereferencing attempt, I assume you need to push anonymous arrays.
#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

my %HoHoA;

push @{$HoHoA{'level 1'}{'numbers'}}, [ 1,2,3,4,5 ];
push @{$HoHoA{'level 1'}{'numbers'}}, [ qw/6 7 8 9 0/ ];


foreach my $top_key ( keys %HoHoA ) {

print "$top_key\n";
foreach my $second_key ( keys %{$HoHoA{$top_key}} ) {

print "\t$second_key\n";
foreach my $array_element ( @{$HoHoA{$top_key}{$second_key}[1]} ) {
print "\t\t$array_element\n";
}
}
}

print Dumper \%HoHoA;


D:\>HoHoA.pl
level 1
numbers
6
7
8
9
0
$VAR1 = {
'level 1' => {
'numbers' => [
[
1,
2,
3,
4,
5
],
[
'6',
'7',
'8',
'9',
'0'
]
]
}
};

naqvia
05-28-2008, 08:21 PM
The code you gave does not print out all of the array elements.. it does not print anything, while if you have a "[0]" on the last loop it prints the array reference.

FishMonger
05-28-2008, 09:58 PM
That would indicate that the structure of your hash differs from my last example. So, it's probably like my first example and with that last nested foreach loop that I posted, it should have printed out the names of the hash keys in both levels. If it didn't, then the actual structure of your hash does not match what you've posted.

Using the example in my first post, which matches the hash structure of your original post, exactly what do you need to output?

naqvia
05-28-2008, 11:02 PM
Here is my hash:

push @{$sequencing_results{$result->query_name}{$type}}, [$hsp->start('query'),$hsp->end('query'),$hit->name,$hsp->start('hit'),$hsp->end('hit'),$hsp->length('hit')."of".$type_length{$type},$result->database_letters,$hsp->percent_identity,$hsp->expect,$hsp->query_string];


I cannot use your first example, because the name of the elements/values are unknown. All I want to do is print it, by iterating through it.

FishMonger
05-28-2008, 11:25 PM
Your latest sample of your hash is pushing an anonymous array, but your first sample wasn't. The construction of the loop will very depending on whether you're using an anonymous array or not.

foreach my $top_key ( keys %sequencing_results ) {

print "$top_key\n";
foreach my $second_key ( keys %{$sequencing_results{$top_key}} ) {

print "\t$second_key\n";
foreach my $array_element ( @{$sequencing_results{$top_key}{$second_key}[0]} ) {
print "\t\t$array_element\n";
}
}
}

If that doesn't do what you need, you'll need to provide the following 3 things.

A more complete sample of your code, which includes your loop that prints the data.
A sample of the EXACT output it generates.
The EXACT output that you expect.