Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort hash by value and key (in that order)

Tags:

sorting

hash

perl

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!

like image 414
TechnoCore Avatar asked Oct 17 '11 09:10

TechnoCore


People also ask

Can you sort a hash by values?

##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!

How do I sort hash keys?

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.

How do I sort a hash by value in Perl?

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}

Can you sort elements in a Ruby hash object?

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)


2 Answers

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";
}
like image 190
sehe Avatar answered Oct 24 '22 01:10

sehe


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
like image 31
Nikhil Jain Avatar answered Oct 24 '22 03:10

Nikhil Jain