Home: Perl Programming Help: Beginner:
Sorting Hash Values



cyberfarer
Novice

Dec 3, 2012, 12:25 PM


Views: 3137
Sorting Hash Values

Hello

I am required to parse a file and sort all alphabetical characters according to frequency from highest to lowest. I am seriously stuck on the sorting and maybe there is a better way to do this. My code:

use strict;
use warnings;

my $cnt = ();
### I don't know why I need this next line but strict complains if I don't have it.
my %cnt = ();

### The file is entered on the command line.
while (<>) { $cnt{lc chop}++ while length }
### Because I only want alpha and I want them all ...
for ('a' .. 'z'){
my @count=(("$_", $cnt{$_}//0));

### Register my hash
my %hcount = ();

### Convert alphas to upper case and assign keys and values.
my $key = uc($_);
my $value = $cnt{$_};

foreach ($key){
$hcount{ $key } = $value;
}
### No matter what I do here, the sort is by alpha and always from A - Z.
foreach $value (sort { $hcount{$b} <=> $hcount{$a} } keys %hcount)
{
print "$value $hcount{$value}\n";
}
}


I appreciate any clues, hints, solutions.

Thanks.


Laurent_R
Veteran / Moderator

Dec 3, 2012, 1:36 PM


Views: 3130
Re: [cyberfarer] Sorting Hash Values

Please try to put your code within code tags, it will preserve its formatting (esp. indentation) and make the code much more readable.

For debugging purpose, you may try to store your sorted items into an array (and then print it, dumpt it or explore it somehow, whatever):

my @sorted_outkeys = sort { $hcount{$b} <=> $hcount{$a} } keys %hcount;

You should see if you get what you expect.


cyberfarer
Novice

Dec 4, 2012, 6:28 AM


Views: 3123
Re: [Laurent_R] Sorting Hash Values

Thank you for the reply, Laurent. I have worked it out. I will take your advice. I am still not clear when code should be within the curly brackets. I'm sure there is likely a clear rule on this, but so far it is evading me.


What worked:

Code
use strict;  
use warnings;

my $cnt;
my %cnt;
my $value;
my $key;
my $hcount;
my %hcount;

while (<>) { $cnt{lc chop}++ while length }

for ('a' .. 'z'){
my @count=(("$_", $cnt{$_}//0));

$key = uc($_);
$value = $cnt{$_}//0;

foreach ($key){
$hcount{ $key } = $value;
}
}

foreach $value (sort { $hcount{$b} <=> $hcount{$a} } keys %hcount)
{
print "$value $hcount{$value}\n";
}



BillKSmith
Veteran

Dec 4, 2012, 7:58 AM


Views: 3110
Re: [cyberfarer] Sorting Hash Values

You have discovered that your main problem was the location of the brace that ended the for loop. You still do not understand the scope of lexical (my) variables. (Refer: perldoc -f my ) (and its links!).

Also you declared several variables which are not needed at all.

With minor clean-up, your code becomes:

Code
use strict; 
use warnings;

my %cnt;
while (<>) { $cnt{ lc chop }++ while length }

my %hcount;
for ( 'a' .. 'z' ) { $hcount{ uc($_) } = $cnt{$_}; }

foreach
my $value ( sort { $hcount{$b} <=> $hcount{$a} or $a cmp $b } keys %hcount )
{
print "$value $hcount{$value}\n";
}

Good Luck,
Bill


cyberfarer
Novice

Dec 4, 2012, 1:26 PM


Views: 3077
Re: [BillKSmith] Sorting Hash Values

Thank you, Bill. That was very helpful. You're right. I don't get it, yet. I will check out the links. Thanks, again.


Laurent_R
Veteran / Moderator

Dec 4, 2012, 2:38 PM


Views: 3074
Re: [cyberfarer] Sorting Hash Values

By far, the main role of the curly braces is to create a block of code that runs usually together and whose execution is determined by some specific condition, such as an "if" conditional or a "while" or a "foreach" loop. You generally want to have all the instructions within the curlies to execute together, depending on whether the condition is true or not.

There are some other reasons to group pieces of code together in a block enclosed within curlies, but this is a slightly more advanced topic, remember for the time being that if you write:


Code
if ($some_condition) { 
instruction 1;
instruction 2;
instruction 3;
}


this means that you want all three instructions to be executed if $some_condition evaluates to true, and none of them if $some_condition is false. Whatever comes after the closing curly is no longer dependent on $some_condition.