2012-07-20 14 views
6

powiedzmy na przykład numery są w formacie:sortować numery z xxxx formatu w Perlu

1.1.10 
1.1.10.1 
1.1.10.2 
1.1.11 
1.1.12 
1.1.13 
1.1.13.1 
1.1.3 
1.1.4 

I wat szukam wyjścia jest:

1.1.3 
1.1.4 
1.1.10 
1.1.10.1 
1.1.10.2 
1.1.11 
1.1.12 
1.1.13 
1.1.13.1 
+0

duplikaty: http://stackoverflow.com/questions/6917314/how-can-i-sort-a-list-of-ip-addresses -in-perl –

+0

Nie jest to duplikat 6917314. Ciągi programu iDev nie mają dokładnie 4 części, a on nie powiedział nic o ograniczeniu do 255. – ikegami

+1

Szybki hack: 'sort {eval $ a cmp eval $ b} @ Numbers' – TLP

Odpowiedz

11
use Sort::Key::Natural qw(natsort); 
my @sorted = natsort @data; 

lub (brak moduły)

my @sorted = 
    map $_->[0], 
    sort { $a->[1] cmp $b->[1] } 
    map [ $_, pack('C*', split /\./) ], 
    @data; 

lub (brak modułów, szybszy, b ut wymaga tablicę zamiast listy dla wejścia)

my @sorted = 
    map $data[unpack('N', $_)], 
    sort 
    map pack('NC*', $_, split /\./, $data[$_]), 
    0..$#data; 

W tych pack szablonów można zmienić C do n lub N. C pozwala na numery do 255. n pozwala na numery do 65 535. N pozwala na liczby do 4 miliardów.

+0

cant dowiedzieć się, jak sortuje się, gdy dostaje pakiet (...) dane, pakiet w tym przypadku po prostu tworzy pojedynczą wartość oktetu z każdego numeru wersji ... nie porównywanie każdej liczby z "cmp" zrobi to samo ? – snoofkin

+0

@ soulSurfer2010, '" 1.2.1 "cmp" 1.16.1 "' nie działa, ponieważ liczby mają zmienną szerokość. Użycie 'pack C' powoduje, że są one tej samej szerokości. Sprowadza się do '" \ x01 \ x02 \ x01 "cmp" \ x01 \ x10 \ x01 "' które sortuje się poprawnie z powodu dopełnienia dodanego. – ikegami

4

Spróbuj wykonać następujące czynności:

use Modern::Perl; 
use Sort::Naturally qw{nsort}; 

my @numbers = nsort(qw{1.1.10 1.1.10.1 1.1.10.2 1.1.11 1.1.12 1.1.13 1.1.13.1 1.1.3}); 
say for @numbers; 

wyjściowa:

1.1.3 
1.1.10 
1.1.10.1 
1.1.10.2 
1.1.11 
1.1.12 
1.1.13 
1.1.13.1 

Nadzieja to pomaga!

0

Może to być łatwiejsze do zrozumienia:

sub min { $_[0] <= $_[1] ? $_[0] : $_[1] } 
sub comp 
    { 
    ($a1,$a2) = @_; 
    @a1 = @{$a1}; 
    @a2 = @{$a2}; 
    for (0..min(scalar @a1,scalar @a2)) 
    { 
    return 1 if $a1[$_] > $a2[$_]; 
    return -1 if $a2[$_] > $a1[$_]; #exit early if an inequality is found 
    } 
    return 0 if @a1 == @a2; #both array are equal, thus both numbers are equal 
    return @a1 > @a2 ? 1 : -1; #arrays are equal upto a certain point, thus longer array is 'greater' 
    } 
@sourcearray = ('1.1.10','1.1.10.1','1.1.10.2','1.1.11','1.1.12','1.1.13','1.1.13.1','1.1.3','1.1.4'); 
@individual = map { [split /\./] } @sourcearray; #splits each number into arrays consisting of individual numbers 
@sorted = sort {comp($a,$b)} @individual; #sort algo decides which of these two arrays are 'greater' 
{ 
local $" = "."; 
print "@{$sorted[$_]}\n" for 0..$#sorted; 
}