2016-04-02 130 views
3

我需要對數字進行排序,我無法按照自己想要的方式工作。Perl自然排序數字

示例輸入:

15.12 
16.1 
15.2 
15.1 

預期輸出:

15.1 
15.2 
15.12 
16.1 

我試圖正常排序,並且還Sort::Naturally此。既不能給我預期的輸出。

我也知道我可以像下面這樣按照我想要的方式進行排序。

my @sorted = 
map sprintf('%vd', $_), 
sort 
map join('', map chr, split /\./), 
@data; 

我想知道是否有一些預先存在的模塊,但我可以使用。

在此先感謝。

回答

3

它看起來像你想的版本號進行排序,其中每個組件是獨立分類。 Sort ::自然不會工作,因爲它忽略了非字母數字字符,但還有其他幾個模塊可以執行此操作。

Sort::Versions分割上週期或連字符的輸入和排序每組任一字母或數字,這取決於非數字字符是否存在:

use strict; 
use warnings 'all'; 
use 5.010; 

use Sort::Versions; 

my @versions = (
    15.12, 
    16.1, 
    15.2, 
    15.1 
); 

say for sort { versioncmp($a, $b) } @versions; 

輸出:

15.1 
15.2 
15.12 
16.1 

排序::版本期望輸入匹配某些常見的版本字符串格式;如果您需要對不同的格式進行排序,請檢查文檔中的規則以確保它適用於您。


Sort::Key::Natural是更加靈活,因爲它分裂的所有單詞邊界,不只是時間和連字符,但在這種情況下,它的工作原理是相同的:

use strict; 
use warnings 'all'; 
use 5.010; 

use Sort::Key::Natural qw(natsort); 

my @versions = (
    15.12, 
    16.1, 
    15.2, 
    15.1 
); 

say for natsort @versions; 

(輸出是一樣的排序: :Versions)

Sort :: Key :: Natural有一些很好的附加功能,比如就地排序和自定義排序順序的能力。在我的基準測試中,它也比Sort :: Versions快得多,儘管如果你對大型數組進行排序,這隻會影響你的工作。

+0

它們看起來像標準的浮點數字給我。假設它們是版本字符串是一個巨大的飛躍 – Borodin

+0

@Borodin看看預期的輸出。他們想在15.12之前分類15.2。 – ThisSuitIsBlackNot

+0

你說得對。這很微妙。好的電話 – Borodin

3

您需要將數字與特殊$a$b變量進行比較(<=>)。請注意,您可以通過用cmp替換<=>來完成對字符串的操作。

use warnings; 
use strict; 

my @nums = qw(15.1 16.1 15.12); 

@nums = sort {$a <=> $b} @nums; 

print "$_\n" for @nums; 

__END__ 
15.1 
15.12 
16.1 
6

如果我的理解是正確的,要通過整數值的數字第一排序,然後再考慮小數部分爲整數本身,因此.12.2更大就像你的榜樣(12> 2)。

我覺得最自明的方法是使用自定義排序,分裂他們之後,你說:

@sorted = sort { 
    my ($a1, $a2) = split /\./, $a; 
    my ($b1, $b2) = split /\./, $b; 
    $a1 <=> $b1 or $a2 <=> $b2 
} @numbers;