简体   繁体   中英

Sort Hash Key and Value simultaneously Perl

I have a hash that I want to sort the keys numerically in ascending order and its values in ascending alphabetically manner.

#!/usr/bin/perl
use warnings;
use strict;
use List::MoreUtils;
use Tie::IxHash;    

my %KEY_VALUE;
#tie %KEY_VALUE,'Tie::IxHash';


my %KEY_VALUE= (
    0 => [ 'A', 'C', 'B', 'A' ,'D'],
    5 => [ 'D', 'F', 'E', ],
    2 => [ 'Z', 'X', 'Y' ],
    4 => [ 'E', 'R', 'M' ],
    3 => [ 'A', 'B', 'B', 'A' ],
    1 => [ 'C', 'C', 'F', 'E' ],
    );

#while (my ($k, $av) = each %KEY_VALUE) 
#{
#  print "$k @$av\n ";
#}

#Sort the key numerically   
foreach my $key (sort keys %KEY_VALUE)
{
 print "$key\n";
}

#To sort the value alphabetically
foreach my $key (sort {$KEY_VALUE{$a} cmp $KEY_VALUE{$b}} keys %KEY_VALUE){
       print "$key: $KEY_VALUE{$key}\n";
}   

The wanted input is like this, and I want to print out the sorted keys and values.

%KEY_VALUE= (
    0 => [ 'A','A','B','C','D'],
    1 => [ 'C','C','E','F' ],
    2 => [ 'X','Y','Z' ],
    3 => [ 'A', 'A', 'B', 'B' ],
    4 => [ 'E','M','R' ],
    5 => [ 'D','E','F', ],
);

Additional problem, how to print the key and the scalar value of the first different value

Wanted Output:

KEY= 0  VALUE:0 2 3 4   #The scalar value of first A B C D, start with 0
KEY= 1  VALUE:0 2 3     #The scalar value of first C E F
KEY= 2  VALUE:0 1 2     #The scalar value of first X Y Z
KEY= 3  VALUE:0 2       #The scalar value of first A B
KEY= 4  VALUE:0 1 2     #The scalar value of first E M R
KEY= 5  VALUE:0 1 2     #The scalar value of first D E F

Hash keys have no defined order. Generally you sort the keys as you're iterating through the hash.

The values can be sorted as you iterate through the hash.

# Iterate through the keys in numeric order.
for my $key (sort {$a <=> $b } keys %hash) {
    # Get the value
    my $val = $hash{$key};

    # Sort it in place
    @$val = sort { $a cmp $b } @$val;

    # Display it
    say "$key -> @$val";
}

Note that by default sort sorts in ASCII order as strings. That means sort keys %KEY_VALUE is not sorting as numbers but as strings. sort(2,3,10) is (10,2,3) . "10" is less than "2" like "ah" is less than "b" . Be sure to use sort { $a <=> $b } for numeric sorting and sort { $a cmp $b } for strings.

You could use a different data structure such as Tie::Ixhash though tying has a significant performance penalty. Generally it's better to sort in place unless your hash gets very large.

You can't sort a hash, you can at best print it sorted (or keep the sorted keys in another array). Finding the position of the first value can be done with first_index ; we remove duplicates with uniq .

foreach my $key (sort keys %KEY_VALUE) {
  my @value = @{$KEY_VALUE{$key}};
  my @indices = map { my $e = $_; first_index { $_ eq $e } @value } (uniq (sort @value));
  print "$key: " . (join ', ', @indices) . "\n";
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM