2011-11-17 109 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 
相關問題