• Publicidad

Ordenar líneas en función de sus campos

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Ordenar líneas en función de sus campos

Notapor explorer » 2007-04-03 08:33 @398

Tenemos un conjunto de líneas de esta forma:
Código: Seleccionar todo
09AAAAABBBBBBTT
02BBBBBBAAAAAAA
15BBBBBAAAAAAAA
11AAAAAABBBBBRR
Como se vé, no hay separador de campos.

Hay que hacer un programa que nos ordene las líneas según los campos indicados en la línea de argumentos del programa. Así, por ejemplo,
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
perl ordenar.pl 2,7 8,12
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4
se refiere a que la ordenación se ha de hacer por dos campos; el primero está desde el carácter 2 hasta el 7 y el segundo, desde el 8 hasta el 12 (las posiciones empiezan en 0).
La salida, con el comando anterior, deberá ser:
Código: Seleccionar todo
11AAAAAABBBBBRR
09AAAAABBBBBBTT
15BBBBBAAAAAAAA
02BBBBBBAAAAAAA
Última edición por explorer el 2007-04-03 08:36 @400, editado 1 vez en total
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Publicidad

Notapor explorer » 2007-04-03 08:35 @399

Una posible solución puede ser esta:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!Perl

# Líneas a procesar
chomp (@lineas = <DATA>);
print join "\n", @lineas;
print "\n"x2;

# Lista de argumentos
$i = 0;
for my $coordenadas ( @ARGV ) {
    my ($inicio,$final) = split q{,}, $coordenadas;
    next unless defined $inicio and defined $final;

    # Lo guardamos en forma inicio,longitud
    push @coordenadas, [ $inicio, $final - $inicio + 1 ];

    # Aprovechamos para construir las comparaciones
    push @comparaciones, "\$a->[$i] cmp \$b->[$i]";
    $i++;
}

$comparaciones = join ' || ', @comparaciones;

# Transformas las líneas a vectores partidos
my @vlineas;
for my $linea ( @lineas ) {
    chomp $linea;
    my @partes;

    for my $coordenada ( @coordenadas ) {
        push @partes, substr($linea,$coordenada->[0],$coordenada->[1]);
    }

    push @vlineas, [ @partes, $linea ];
}

# Hacemos la ordenación por medio de una semi-transformada de Schwartz:
# En el bucle anterior hemos hecho el mapeado del conjunto de datos de partida
# a una lista de elementos que son a la vez listas de elementos, que son,
# primero, los subconjuntos de la línea que tenemos que comparar, y seguidos
# por la propio línea.
# El método de ordenación se construyó en el primer bucle, en un escalar. Es
# decir, hemos construído código Perl en función de los argumentos.
# La función sort ejecutará el código que está almacenado en el escalar, por
# medio de eval.
# Finálmente, del array ordenado obtenemos las líneas originales.
@lineas
    = map  { $_->[-1]            }
      sort { eval $comparaciones }
      @vlineas;

print join "\n", @lineas;
print "\n"x2;

__DATA__
09AAAAABBBBBBTT
02BBBBBBAAAAAAA
15BBBBBAAAAAAAA
11AAAAAABBBBBRR
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


Sería interesante ver una solución usando el comando unpack, por ejemplo.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 11 invitados