I'm looking for a nice way to sort a hash in Perl by value first and by key afterwards.
Example:
my %userids = (
williams => "Marketing",
smith => "Research",
johnson => "Research",
jones => "Marketing",
brown => "Marketing",
davis => "Research"
);
Output:
Marketing: brown
Marketing: jones
Marketing: williams
Research: davis
Research: johnson
Research: smith
Please note that value was the first sorting level. Second sorting level is key. Any idea how to do this in an elegant and high-performance way? Thanks!
##Hash#keys and Hash#values A simple way to sort a hash keys or values is to use the methods Hash#keys and Hash#values. Those 2 methods are simply returning an array of the keys or the values of your hash. So as soon as you get an array with only one of the type of values you want to work with, it's all good!
Unfortunately, there is no direct way to sort the hash by keys. However, we can use the values method to fetch the hash values and sort them. Once we execute the above command, we should get the values of the hash sorted in array format.
For example we can sort the hash first by the Position value, and among the entries with the same Position value we can sort by the value of the Max field. In order to do this we will use the following expression: my @maxed = sort { $data->{$a}{Position} <=> $data->{$b}{Position}
You can use the sort method on an array, hash, or another Enumerable object & you'll get the default sorting behavior (sort based on <=> operator) You can use sort with a block, and two block arguments, to define how one object is different than another (block should return 1, 0, or -1)
Good reference: http://www.misc-perl-info.com/perl-sort.html#shv
#!/usr/bin/perl
my %userids = (
williams => "Marketing",
smith => "Research",
johnson => "Research",
jones => "Marketing",
brown => "Marketing",
davis => "Research"
);
foreach (sort { ($userids{$a} cmp $userids{$b}) || ($a cmp $b) } keys %userids)
{
print "$_: $userids{$_}\n";
}
I would like to add one more thing, use \L sequence
in sorting.
From Perlfaq4: How do I sort a hash (optionally by value instead of key)?
To make our report order case-insensitive, we use the \L sequence
in a double-quoted string to make everything lowercase. The sort()
block then compares the lowercased values to determine in which order to put the keys.
foreach (sort { $userids{$a} cmp $userids{$b} or "\L$a" cmp "\L$b" ) {
print "$_: $userids{$_}\n";
}
Output :
brown: Marketing
jones: Marketing
williams: Marketing
davis: Research
Johnson: Research # here 'J'ohnson, J is in uppercase(taking assumption), come as fifth record
smith: Research
2.
foreach (sort { $userids{$a} cmp $userids{$b} or $a cmp $b ) {
print "$_: $userids{$_}\n";
}
Output:
brown: Marketing
jones: Marketing
williams: Marketing
Johnson: Research # here it shifted to fourth record
davis: Research
smith: Research
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With