2011-11-17 136 views
4

我正在尝试对文件进行散列工作,并且工作必须按特定顺序完成。大多数人会说,列表可以像这样被下令:在Perl中,如何使用自定义排序对散列键进行排序?

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

不过,我需要非字母的顺序,其实键启动一个字,然后_和他们去GdigitsL任何的M,P,R,T or D(如。 word_G.txtword_2.txt,...,word_P.txt)。有没有什么办法按自定义顺序排序?

+0

只要把你的排序条件排序关键字后面:'而我的$ K(排序{$一个<$ B,除非$一个EQ '_'}键%my_hash)'等... –

回答

12

有没有什么办法按自定义顺序排序?

是的。见sort

例如:

#!/usr/bin/env perl 

use warnings; use strict; 

my @order = qw(G 1 2 3 L M P R T D); 

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"; 
+0

我看到比较原型,我认为是我想要的,但我可以看到的唯一解决方案是一堆if语句。这是唯一的方法吗? –

+1

你没有很好地解释你的要求,所以我不能真正弄清楚什么可以解决特定的问题。要以非默认方式排序,您需要编写一个比较函数。如果您解释该功能需要做,我们可能会提供帮助。 –

+0

我认为这是我所能解释的,所以让我们以不同的方式。而不是比较'A,B,C,...,X,Y,Z'我想要'G,1,2,3,L,M,P,R,T,D' –

4
use 5.014; 

sub rank { 
    my ($word) = @_; 
    $word =~ s{\A \w+ _}{}msx; 
    return do { 
     given ($word) { 
      0 when /\A G/msx; 
      1 when /\A [0-9]/msx; 
      2 when /\A L/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); 

输出:

word_G.txt 
word_2.txt 
word_P.txt 

编辑:Perl的5.14之前,使用一个临时变量。

use 5.010; 
⋮ 
return do { 
    my $dummy; 
    given ($word) { 
     $dummy = 0 when /\A G/msx; 
     $dummy = 1 when /\A [0-9]/msx; 
     $dummy = 2 when /\A L/msx; 
     $dummy = 3 when /\A [MPRTD]/msx; 
     default { $dummy = 1000 }; 
    } 
    $dummy; 
}; 
+0

我复制粘贴你的解决方案到Perl,它给我没有错误,但订单P,2,G这是提供的订单... –

+0

按照http://p3rl.org/perl5140delta#given-return - 值 – daxim

+0

对不起,我没有5.014 –

0

我有一个具体的用例,我想先排序某些值,其他值最后排序,然后按字母顺序排列在中间。

这里是我的解决方案:

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; 

输出:

$ perl customsort.pl Tom Z Mike A Joe X Dave G 
Mike Dave A G X Z Tom Joe 
相关问题