2014-11-23 81 views
4

我在Perl與像一些間隔的數組:在perl中對間隔數組進行排序?

@array = QW(1-5 7-9 10-15 20-58 123-192 234-256)

我我試圖使用排序來訂購吧,但是這是我獲得:

1-5,10-15,123-192,20-58,234-256,7-9

它按照排序第一個數字的第一個字符......如何才能按整個第一個數字排序才能獲得下一個數組?

1-5,7-9,10-15,20-58,123-192,234-256

非常感謝您!

P.S.

我對這個沒有代碼,我試圖命令

my @sorted = sort @array; 
+0

'7-9'會在'7-11'之前嗎? – TLP 2014-11-23 13:36:12

+1

顯示您嘗試過的代碼。你需要指定你自己的排序程序。 – TLP 2014-11-23 13:42:05

+0

這不是必要的,在數據​​集中不可能發生這種情況,但是如果這樣做更容易,那就沒有問題了。 – Shikari 2014-11-23 13:42:33

回答

5

你需要提取第一個數字爲每一個元素,並使用<=>運營商做的數值比較,

my @array = qw(1-5 7-9 10-15 20-58 123-192 234-256); 
my @sorted = sort { 
    my ($aa,$bb) = map /^([0-9]+)/, $a,$b; 

    $aa <=> $bb; 
} @array; 
+0

它完美地工作,非常感謝! – Shikari 2014-11-23 13:48:57

+0

@mpapec,我幾乎發佈,但沒有完全清醒......現在我仍然試圖找出爲什麼我的@sorted = sort {map/^([0-9] +)/,$ a,$ b; $ a <=> $ b} @array;'是不夠的(TLP解釋了它的一部分)。 – 2014-11-23 17:57:41

+0

@ G.Cito我不確定你指的是什麼;它是第二種排序標準嗎? – 2014-11-23 18:11:38

5

什麼你想要做的是按數字排序。要做到這一點,您需要通過提供自己的方法來覆蓋默認的排序方法。此代碼:

my @sorted = sort @array; 

真正含義:

my @sorted = sort { $a cmp $b } @array; 

哪裏cmp是逐一比較操作(排序按字母順序排列,或多或少)。你想使用<=>,通常稱爲「太空船操作員」。

my @sorted = sort { $a <=> $b } @array; 

但這種操作只能用數字來使用,一個字符串,如7-9是不是一個真正的數字(儘管在這種情況下,它會工作,儘管發出警告Argument "7-9" isn't numeric in sort)。

爲了克服這個警告和可能的錯誤,我們需要從我們想要排序的字符串中提取數字。我們用正則表達式匹配:/\d+/g。這將匹配並返回字符串中的所有連續數字。

my @sorted = sort { 
        my ($a1, $a2) = $a =~ /\d+/g; 
        my ($b1, $b2) = $b =~ /\d+/g; 
        $a1 <=> $b1 || $a2 <=> $b2; 
} @array; 

我們捕獲並使用低和高範圍,最後我們執行兩個檢查。這意味着,在該$a1$b1相等,<=>返回0,並且||操作者的情況下執行所述替代比較,$a2 <=> $b2

在某些情況下,這種操作是昂貴的,這需要時間,並配有大型數據集,這將導致排序變得非常緩慢。在這種情況下,我們可以使用所謂的Schwartzian transform來緩存數據。在這種方法中,我們只需存儲正則表達式匹配的值並在排序時使用存儲的值。爲此,我們使用匿名數組ref [ ... ]。最後,我們恢復原值,並丟棄緩存:

my @sorted = map { $_->[0] }    # restore original 
      sort { $a->[1] <=> $b->[1] } # sort compares stored nums 
      map { [ $_, /\d+/g ] }   # store original, and nums 
      @array; 

如果你想要一個以上的水平排序,你只需要添加$a->[2] <=> $b->[2]等。

+1

非常好的答案,我正在學Perl,這種東西對我來說非常有用,非常感謝! – Shikari 2014-11-23 14:13:38

+0

不客氣。 – TLP 2014-11-23 14:13:56