• Publicidad

Ordenar Hashes por valores

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

Ordenar Hashes por valores

Notapor Yazston » 2008-04-02 16:52 @744

Buenas, ante todo muchas gracias y cómo no, comento, por una duda que tengo. Veréis, tengo un programilla: que tiene que coger datos de un archivo que le introducimos como parámetro ($ARGV).

Pues bien, esos parámetros se separan por tabulaciones y lo que quiero es coger el primer valor como clave para un hash y los valores 4 y 5 (3 y 4 empezando de 0) como valores de esa clave. Y después mostrarlos ordenando de mayor a menor en función de restar al valor 5 el valor 4. Me explico, en el archivo cogeríamos esto:

Código: Seleccionar todo
Valor 1  valor 4      valor5   resta (la resta la hace el programa)
nombre1       40         100      60
nombre2      200         500     300
nombre3      400         480      80


entonces nos saldría así:

Código: Seleccionar todo
nombre2      200         500
nombre3      400         480
nombre1       40         100


Bien, yo mirando el foro y así, he sacado esto...

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my $file = $ARGV[0];
open (IN, "$file") or die ("cannont open the file \n");
my %hash;
while (<IN>) {
    chomp;
    my @v = split (/\s+/,$_);
    my @lista;
    push (@lista, $v[3]);
    push(@lista,$v[4]);
    my $lista_ref = $v[4]-$v[3];
    push(@lista,$lista_ref]);
    push (@{$hash{$v[0]}}, $lista);
}
foreach my $chr (keys %hash)  {
    my @sorted_exons = sort {abs($b ->[2]) <=> abs($a -> [2])}  @{$hash{$chr}};
    foreach my $exon (@sorted_exons) {
        print ("$exon\n");
    }
}
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


Y el problema ahora es que donde el print ("$exon\n"), no consigo poner para que salga $clave $valor0 $valor1, es decir, pensaba en hacer un while ($clave, @valor) = each (%hash) e ir sacando, pero donde valor, lo que me muestra es ARRAY234fc93 y así.

Así que me toca probar a ver si alguno sabría decirme. Muchas gracias de antemano.

Yo tengo que sacar así:
Código: Seleccionar todo
Clave Valor Valor
Yazston
Perlero nuevo
Perlero nuevo
 
Mensajes: 3
Registrado: 2008-04-02 16:31 @729

Publicidad

Notapor explorer » 2008-04-02 18:57 @831

Bienvenido a los foros de Perl en Español, Yazston.

Un problema que he visto es que la variable $lista que usas en el último push, no está inicializada.

Es recomendable usar use strict; para que Perl nos ayude a encontrar estos problemas.

Otra idea: cuando estamos creando una estructura de datos que puede complicarse, hay que recordar que el módulo Data::Dumper, es nuestro más fiel amigo.

Otro detalle: si quieres que salga $clave en la primera columna, recuerda que está en la variable $chr, por lo que tendrás que hacer un print específico para él.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor explorer » 2008-04-05 14:10 @632

Esta es una posible solución:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
        1 #!/usr/bin/perl
        2 use warnings;
        3 use strict;
        4
        5 my $fichero = $ARGV[0] or die;
        6 open IN,"<$fichero" or die "cannont open the file\n";
        7
        8 my %hash;
        9
       10 while ( <IN> ) {
       11
       12     chomp;
       13
       14     my @v = split;
       15
       16     my @lista = ( $v[3], $v[4], abs($v[4] - $v[3]) );
       17
       18     $hash{ $v[0] } = \@lista;
       19 }
       20
       21 #use Data::Dumper;
       22 #print Dumper(\%hash);
       23
       24 my @claves_ordenadas
       25     = sort {
       26         $hash{$b}->[2] <=> $hash{$a}->[2];
       27     } keys %hash;
       28
       29 foreach my $clave ( @claves_ordenadas )  {
       30
       31     my @columnas = ( $hash{ $clave }->[0], $hash{ $clave }->[1] );
       32
       33     print join("\t", ( $clave, @columnas )), "\n";
       34 }
       35
       36 close IN;
       37
       38 __END__
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Esto es lo que hace:
  • 14. Extrae las columnas de la línea
  • 16. Guardamos las columnas cuarta, quinta y su diferencia absoluta
  • 18. Guardamos una referencia a ese array como valor de un hash cuya clave es el de la primera columna
  • 21.22. Podemos descomentar esas líneas para ver el aspecto que tiene el %hash
  • 24 a 27. Sacamos una lista de las claves, ordenadas por el valor numérico de los valores, en orden inverso
  • 29 a 34. Lo sacamos en pantalla. Otra forma de sacar los dos primeros valores de cada array anónimo: @{$hash{$clave}}[0,1].
  • 33. Con la ayuda de join, sacamos tanto la clave como los valores
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor Yazston » 2008-04-09 04:33 @231

Muchas gracias a todos. Como al final solo tenía que almacenar los valores y no la resta, hice esto. Os lo dejo por si le puede interesar a alguien.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my $file = $ARGV[0];
open (IN, "$file") or die ("cannont open the file \n");
my %hash;
while (<IN>) {
    chomp;
    my @v = split (/\s+/,$_);
    my @lista;
    push (@lista,$v[3]);
    push (@lista,$v[4]);
    my $lista_ref = \@lista;
    push (@{$hash{$v[0]}}, $lista_ref);
}
foreach my $chr (keys %hash)  {
    my @sorted_exons =sort {abs($b -> [1] - $b -> [0]) <=> abs($a -> [1] - $a -> [0])} @{$hash{$chr}};
    foreach my $exon (@sorted_exons) {
        print ("La clave $chr con valores ".$exon ->[1]." y ".$exon ->[0]."\n");
    }
}
close IN;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Yazston
Perlero nuevo
Perlero nuevo
 
Mensajes: 3
Registrado: 2008-04-02 16:31 @729


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado

cron