How to sort perl hash on values and order the keys correspondingly (in two arrays maybe)?

南楼画角 提交于 2019-12-17 18:06:35

问题


In Perl, I want to sort the keys of a hash by value, numerically:

{
  five => 5
  ten => 10
  one => 1
  four => 4
}

producing two arrays:

(1,4,5,10) and (one, four, five, ten)

And then I want to normalize the values array such that the numbers are sequential:

(1,2,3,4)

How do I do this?


回答1:


First sort the keys by the associated value. Then get the values (e.g. by using a hash slice).

my @keys = sort { $h{$a} <=> $h{$b} } keys(%h);
my @vals = @h{@keys};

Or if you have a hash reference.

my @keys = sort { $h->{$a} <=> $h->{$b} } keys(%$h);
my @vals = @{$h}{@keys};



回答2:


How do I sort a hash (optionally by value instead of key)?

To sort a hash, start with the keys. In this example, we give the list of keys to the sort function which then compares them ASCIIbetically (which might be affected by your locale settings). The output list has the keys in ASCIIbetical order. Once we have the keys, we can go through them to create a report which lists the keys in ASCIIbetical order.

my @keys = sort { $a cmp $b } keys %hash;

foreach my $key ( @keys ) {
    printf "%-20s %6d\n", $key, $hash{$key};
}

We could get more fancy in the sort() block though. Instead of comparing the keys, we can compute a value with them and use that value as the comparison.

For instance, to make our report order case-insensitive, we use lc to lowercase the keys before comparing them:

my @keys = sort { lc $a cmp lc $b } keys %hash;

Note: if the computation is expensive or the hash has many elements, you may want to look at the Schwartzian Transform to cache the computation results.

If we want to sort by the hash value instead, we use the hash key to look it up. We still get out a list of keys, but this time they are ordered by their value.

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

From there we can get more complex. If the hash values are the same, we can provide a secondary sort on the hash key.

my @keys = sort {
$hash{$a} <=> $hash{$b}
or
"\L$a" cmp "\L$b"
} keys %hash;



回答3:


Please see the Perl FAQ entry titled "How do I sort a hash (optionally by value instead of key)"

http://perldoc.perl.org/perlfaq4.html#How-do-I-sort-a-hash-%28optionally-by-value-instead-of-key%29?

You can also use perldoc -q to search the FAQ locally on your machine, as in perldoc -q sort, which is how I found your answer.




回答4:


my ( @nums, @words );
do { push @nums,  shift @$_; 
     push @words, shift @$_; 
   }
    foreach sort { $a->[0] <=> $b->[0] } 
            map  { [ $h->{ $_ }, $_ ] } keys %$h
   ;


来源:https://stackoverflow.com/questions/10901084/how-to-sort-perl-hash-on-values-and-order-the-keys-correspondingly-in-two-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!