2012-11-14 31 views
4

任何人都有任何想法如何按長度對數字進行排序?在Perl中按長度排序

例如:(11,111,122,12,2,13,21,15,211,22,213,2004)

我想數組排序爲:

11 
12 
13 
15 
111 
122 
2 
21 
22 
213 
2004
+0

您的輸出中缺少'211'。 –

回答

6

所需的輸出似乎表明你不只是想按數字的數量排序,而是先按第一位數字排序,然後再按長度排序。

您所要顯示的輸出省略了211,所以我只是根據我的理解將它放在了它所屬的位置。

#!/usr/bin/env perl 

use strict; 
use warnings; 

use Test::More; 

my @source = (11, 111, 122, 12, 2, 13, 21, 15, 211, 22, 213, 2004); 
my @desired = (11, 12, 13, 15, 111, 122, 2, 21, 22, 211, 213, 2004); 

my @sorted =sort { 
    substr($a, 0, 1) <=> substr($b, 0, 1) || 
    length($a) <=> length($b) || 
    $a <=> $b # thanks @ikegami 
} @source; 

is_deeply(\@sorted, \@desired, 'Sorted and desired are the same'); 
+2

這可能很容易給15,13,​​12,11,...作爲11,12,13,15,...不知道這是否重要。 – ikegami

+0

謝謝@Sinan, 這就是我要找的。 實際上,我想在散列函數中實現它,訂單號碼是關鍵。我如何能做到這一點。?感謝您的幫助 –

+0

呵呵?你是否要求(for sort ... keys(%hash)){$ hash {$ _}}? – ikegami

2
my @sorted = 
    sort { substr($a,0,1) <=> substr($b,0,1) || $a <=> $b } 
    @unsorted; 

給你所要求的訂單。或者,也許你想

my @sorted = 
    sort { substr($a,0,1) <=> substr($b,0,1) 
     || length($a) <=> length($b) 
     || $a <=> $b } 
    @unsorted; 

如果211不是從你提供的輸出失蹤,我能會告訴你,你要哪一個。

2

考慮所謂的Schwartzian transform,從而避免了通過暫時將它們與輸入項目相關聯重新計算排序關鍵字:

my @sorted = 
    map { $_->[0] } 
    sort { $a->[1] cmp $b->[1] or $a->[0] <=> $b->[0] } 
    map { [ $_ => sprintf "%.1s%08x", $_, length ] } 
    @source; 
+0

請參閱'List :: Utils :: sort_by' – LeoNerd

+0

您的意思是List :: UtilsBy :: sort_by,對嗎?順便說一句,同意,它絕對應該被合併到List :: Util/List :: MoreUtils!那個Eryes, – creaktive

+0

。恥辱我無法編輯評論。 – LeoNerd

1

這是由List::UtilsBy::sort_by

use List::UtilsBy qw(sort_by); 

my @sorted = sort_by { sprintf "%.1s%08x", $_, length } @source; 

這是一樣一樣的提供其他人建議的Schwartzian Transform解決方案,但是包含在一個簡潔的抽象中。