In Perl, how can I sort hash keys using a custom order?

I am trying to work with a hash of files, and the work should be done in a specific order. Most will say that the list can be sorted like this:

for my $k (sort keys %my_hash) { print "$k=>$my_hash{$k}, "; } 

However, I need a non-alphabetical order, in fact, the keys begin with the word then _ , and they go from G to digits to L to any of M,P,R,T or D (for example, word_G.txt , word_2.txt , .. ., word_P.txt ). Is there a way to sort by custom?

+4
source share
3 answers

Is there a way to sort by custom?

Yes. See sort .

For instance:

 #!/usr/bin/env perl use warnings; use strict; my @order = qw(G 1 2 3 LMPRTD); my %order_map = map { $order[$_] => $_ } 0 .. $#order; my $pat = join '|', @order; my @input = qw(word_P.txt word_2.txt word_G.txt); my @sorted = sort { my ($x, $y) = map /^word_($pat)[.]txt\z/, $a, $b; $order_map{$x} <=> $order_map{$y} } @input; print "@sorted\n"; 
+12
source
 use 5.014; sub rank { my ($word) = @_; $word =~ s{\A \w+ _}{}msx; return do { given ($word) { 0 when /\AG/msx; 1 when /\A [0-9]/msx; 2 when /\AL/msx; 3 when /\A [MPRTD]/msx; default { 1000 }; } }; } say for sort { rank($a) <=> rank($b) } qw(word_P.txt word_2.txt word_G.txt); 

Output:

 word_G.txt word_2.txt word_P.txt 

Edit: Before Perl 5.14, use a temporary variable.

 use 5.010; โ‹ฎ return do { my $dummy; given ($word) { $dummy = 0 when /\AG/msx; $dummy = 1 when /\A [0-9]/msx; $dummy = 2 when /\AL/msx; $dummy = 3 when /\A [MPRTD]/msx; default { $dummy = 1000 }; } $dummy; }; 
+4
source

I had a specific use case when I first wanted to sort with specific values, other values โ€‹โ€‹last, then everything else in alphabetical order in the middle.

Here is my solution:

 my @sorted = sort { my @order = qw(Mike Dave - Tom Joe); my ($x,$y) = (undef,undef); for (my $i = 0; $i <= $#order; $i++) { my $token = $order[$i]; $x = $i if ($token eq $a or (not defined $x and $token eq "-")); $y = $i if ($token eq $b or (not defined $y and $token eq "-")); } $x <=> $y or $a cmp $b } @ARGV; 

Output:

 $ perl customsort.pl Tom Z Mike A Joe X Dave G Mike Dave AGXZ Tom Joe 
0
source

Source: https://habr.com/ru/post/1381763/


All Articles