2015-01-14 129 views
2

我需要使用perl對散列鍵進行排序,我還需要允許key中的重複。所以我打算檢查exists方法perl
如果它存在然後我增加最後一位數然後我將存儲到哈希。 我嘗試下面的代碼:使用perl進行散列鍵排序?

use strict; 
use warnings; 
use iPerl::Basic qw(_save_file _open_file); 
my $xml = $ARGV[0]; 
my ($xmlcnt,$backcnt,$refcnt,$name,$year) = ""; 
my %sort =(); 
if(($#ARGV != 0) or(not -f "$xml") or($xml!~ m{\.xml$}i)){ 
    print_exit("\t\tSYSTAX ERROR: <EXE> <xml File>\n\n") 
}; 
$xmlcnt=_open_file($xml); 
$xmlcnt =~ s{<back(?: [^>]+)?>(?:(?!</?back[ >]).)*</back>}{ 
    $backcnt = $&; 

    while($backcnt =~ m{<ref(?: [^>]+)?>(?:(?!<ref[ >]).)*</ref>}igs){ 
     $refcnt = $&; 
     $name = $1 if($refcnt =~ m{<person-group(?: [^>]+)?>((?:(?!</?person-group[ >]).)*)</person-group>}is); 
     $year = $1 if($refcnt =~ m{<year>((?:(?!</?year[ >]).)*)</year>}is); 
     $name =~ s{</?(?:string-name|surname|given-names)>}{}ig; 
     my $count = 1; 
     my $keys="$name $year\E$count"; 

     if(exists ($sort{$keys})){ 

      $keys =~ s{(\d)$}{my $icr=$1;$icr++;qq($icr)}e; 

      #print"$keys\n"; 
      $sort{$keys}="$refcnt"; 

     } 
     else 
     { 
      $sort{$keys}="$refcnt"; 
     } 


print join("\n",keys %sort); 
    } 
qq($backcnt) 
}igse; 

    my @keys = sort { 
$sort{$a} <=> $sort{$b} 
# or 
# "\L$a" cmp "\L$b" 
} keys %sort; 
# print join("\n",@keys); 
sub print_exit { 
    my $msg = shift; 
    #print "\n$msg"; 
    exit; 
} 

請誰能告訴我出了什麼錯在這裏?
輸入:

thieooieroh 
apple 
apple 
highefhfe 
bufghifeh 

輸出:

apple 
apple 
bufghifeh 
highefhfe 
thieooieroh 

預先感謝。

+3

哎唷!我的眼睛!替換命令替換部分中的25行塊可執行代碼殘酷地可怕!我甚至不想看它;真是太可怕了。如果您必須執行代碼,請將其放入函數中,並使用substitute命令調用該函數。 –

+0

這裏他們使用替代,希望在散列鍵中存儲文本。問題是如果文本已經存在於文本末尾,則爲重複值添加整數,然後最後對鍵進行排序。 – depsai

+1

請勿使用正則表達式來分析xml。永遠。看看'死亡'。這是你的'print_exit'的正確替代。出於性能原因,你應該避免'$&'(你可以,如果你引入一個匹配組並使用'$ 1')。簡單的散列可能是錯誤的數據結構。你可以使用數組的散列。 –

回答

2

從您的代碼的簡要介紹看來,您希望將refcounts存儲爲散列中的值,並且能夠對單個鍵進行多次計數。這很容易通過使用數組的散列(通常縮寫爲HoA)來實現。按照定義,每個鍵必須是唯一的,但相關聯的值可以是引用,允許您在該鍵下存儲多個項目,或者構建更復雜的數據結構。

#!/usr/bin/env perl  

use strict; 
use warnings; 
use 5.010; 

my %hash; 

while (my $line = <DATA>) { 
    chomp $line; 
    my ($key, $count) = split ',', $line; 
    push @{$hash{$key}}, $count; 
} 

for my $key (sort keys %hash) { 
    my $values = $hash{$key}; 
    for (@$values) { 
    say "$key ($_)"; 
    } 
} 

__DATA__ 
thieooieroh,1 
apple,2 
apple,3 
highefhfe,4 
bufghifeh,5 

輸出:

apple (2) 
apple (3) 
bufghifeh (5) 
highefhfe (4) 
thieooieroh (1) 

如果你沒有真正關心存儲與每個鍵多個數據項,但只有隨着時代出現的每個按鍵的數量,這是更簡單。改變兩個環路在上面的代碼:

while (my $line = <DATA>) { 
    chomp $line; 
    $hash{$line}++; 
} 

for my $key (sort keys %hash) { 
    say $key for 1 .. $hash{$key}; 
} 

,你得到的輸出

apple 
apple 
bufghifeh 
highefhfe 
thieooieroh 

至於你貼的代碼休息,不要試圖用正則表達式解析XML。任意XML 不能被表達式解析超出非常粗略的第一近似值常規表達式,因爲XML在結構上不是「常規」的。 CPAN上有很多很好的XML解析模塊,它們會爲你正確解析你的XML,同時也比你試圖編寫你自己的解析器需要更少的努力。使用其中之一。不是正則表達式。

相關問題