Hash hashes: how to get the number of occurrences of a key?

I have the following text file.

foo1 bam foo1 bam foo2 bam foo1 zip foo2 boo foo1 zip foo3 zip 

I would like to make a hash hash where KEY1 is column one , KEY2 is the sound it makes ( column two ): bam , zip , or boo , and VALUE is the number of occurrences of this sound. Thus, the data structure looks like this:

 $VAR1 = { 'foo1' => { 'bam' => [ 2 ], 'zip' => [ 2 ], }, 'foo2' => { 'bam' => [ 1 ], 'boo' => [ 1 ], }, 'foo3' => { 'zip' => [ 1 ], } } 

That's what i still have

 use strict; use warnings; open(my $fh, '<', 'file.txt') or die $!; my %HoH; while(<$fh>){ chomp; my @cols = split(/\t/, $_); my $KEY1 = $cols[0]; my $KEY2 = $cols[1]; push( @{$HoH{$KEY1}{$KEY2}}, 1); # This actually creates a hash of hash of arrays } my %HoH_final; foreach my $KEY1 (%HoH) { foreach my $KEY2 (keys %HoH{$KEY1}){ my $count = scalar @{$HoH{$KEY1}{$KEY2}}; # get the size of that array push( @{$HoH_final{$KEY1}{$KEY2}}, $count); } } 

What do you think?

+4
source share
3 answers

You do not need the following data structure?

 { 'foo1' => { 'bam' => 2, 'zip' => 2, }, ... } 

If yes,

 while (<$fh>) { chomp; my @cols = split /\t/; ++$HoH{ $cols[0] }{ $cols[1] }; } 

If you really need singleton arrays,

 while (<$fh>) { chomp; my @cols = split /\t/; ++$HoH{ $cols[0] }{ $cols[1] }[0]; } 
+5
source

Is there a reason why every second-level key points to arrayref instead of a number? I would recommend doing this as follows:

 while(<$fh>){ chomp; my @cols = split(/\t/, $_); $HoH{ $cols[0] }{ $cols[1] }++; } 

This will increase ( ++ ) the value on each second-level key when it occurs.

+3
source

It actually does the trick

  perl -F'\t' -ane'$h{$F[0]}{$F[1]}++' 

If you want to see the result

  perl -MData::Dumper -F'\t' -ane'$h{$F[0]}{$F[1]}++}{print Dumper(\%h)' 
+3
source

All Articles