2012-07-20 11 views
6

decir, por ejemplo los números están en formato:Ordenar números con el formato xxxx en Perl

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 

Y el wat Busco salida es:

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

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

+0

No es un duplicado de 6917314. Las cadenas de iDev no tienen exactamente 4 partes, y él no dijo nada sobre ellas estando limitado a 255. – ikegami

+1

Hack rápido: 'sort {eval $ a cmp eval $ b} @ numbers' – TLP

Respuesta

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

o (sin módulos)

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

o (sin módulos, más rápido, b UT requiere una matriz en lugar de una lista para la entrada)

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

En los pack plantillas, puede cambiar C-n o N. C permite números de hasta 255. n permite números de hasta 65,535. N permite números de hasta 4 mil millones.

+0

no puedo entender cómo funciona el género cuando obtiene los datos del paquete (...), el paquete en este caso solo crea un valor de octeto único de cada número de versión ... no comparar cada número con 'cmp' hará lo mismo ? – snoofkin

+0

@ soulSurfer2010, '" 1.2.1 "cmp" 1.16.1 "' falla porque los números tienen un ancho variable. Usando 'pack C', hace que todos tengan el mismo ancho. Se reduce a '" \ x01 \ x02 \ x01 "cmp" \ x01 \ x10 \ x01 "' que ordena correctamente debido al relleno agregado. – ikegami

4

intente lo siguiente:

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; 

Salida:

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 

Espero que esto ayude!

0

Esto puede ser más fácil para que usted pueda comprender:

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; 
} 
Cuestiones relacionadas