• Publicidad

Filtrar lista usando hashes

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

Filtrar lista usando hashes

Notapor Alfumao » 2013-01-03 04:41 @237

Hola a todos,

Planteo aquí un problema que seguramente será muy básico, pero en el que me he atascado como el tontaina que soy.
Pretendo filtrar una lista donde aparece el mismo nombre varias veces pero con valores diferentes y quiero quedarme con el menor de los valores que aparecen para cada nombre.

Este sería un ejemplo de la lista.
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
IDX2    10
IDX4    11
IDX5    12
IDX7    14
IDX12   15
IDX2    10
IDX4    11
IDX5    12
IDX7    14
IDX5    17
IDX6    2
IDX12   37
IDX6    4
IDX12   5
IDX5    6
IDX5    8
IDX6    9
IDX12   15
IDX2    16
IDX4    17
IDX5    18
IDX6    19
IDX7    20
IDX12   21
IDX2    16
IDX4    17
IDX5    18
IDX6    19
IDX7    20
IDX12   21
IDX5    0.1
IDX6    0.2
IDX12   0.3
IDX2    0.10
IDX4    0.11
IDX7    0.14
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Escribí un código pero los resultados me salen duplicados (es decir para cada nombre de la lista me sale el menor valor pero también otro...)

Ejemplo de resultado erróneo:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
IDX12    5
IDX5     6
IDX5     0.1
IDX6     0.2
IDX12    0.3
IDX2     0.10
IDX4     0.11
IDX7     0.14
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Aquí va el código:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use diagnostics;
  5. use Getopt::Long;
  6.  
  7. #usage: perl /path_to/hash_order.pl -t /path_to/file.txt
  8.  
  9. my ( $target);
  10. GetOptions(
  11.     'table=s'     => \$target,
  12.      );
  13.  
  14. open(INFILE,"$target") or die ("ERROR: $!\n");
  15. chomp (my @lineas = <INFILE>);
  16. open  SALIDA,'>/path_to/hash_order.txt' or die "ERROR: $!\n";
  17. my %unique=();
  18.  
  19. for(@lineas){
  20. if (/^\w+/){
  21.  
  22. my ($feat,$pval) = split(/\t/, $_);
  23.     print "$feat\n";
  24.     my $href=\%unique;
  25.     &comphash ($feat,$pval,$href)
  26.    
  27.     }
  28. }
  29.  
  30. sub comphash{
  31.    my($feat,$pval,%{href})=@_;
  32.    
  33.    if(exists $unique{$feat}){
  34.        if($pval< $unique{$feat}){
  35.           $unique{$feat}=$pval;
  36.           print SALIDA "$feat\t $unique{$feat}\n";
  37.        }else{
  38.              next;
  39.             }
  40.     }else{
  41.        $unique{$feat}="$pval";
  42.        #print SALIDA "$feat\t $unique{$feat}\n";
  43.     }
  44.     }
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


¿Me podéis ayudar a encontrar el error?

Mil Gracias
Alfumao
Perlero nuevo
Perlero nuevo
 
Mensajes: 178
Registrado: 2009-12-10 11:20 @514

Publicidad

Re: Filtrar lista usando hashes

Notapor explorer » 2013-01-03 12:58 @581

El error está en imprimir (línea 36) cuando no se ha terminado de leer todo el archivo, por lo que estás imprimiendo varias soluciones, en lugar de una sola.

Solución: hacer un recorrido extra al final de todo el procesado, para sacar las claves correctas:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use diagnostics;
  5.  
  6. use Getopt::Long;
  7.  
  8. # usage: perl /path_to/hash_order.pl -t /path_to/file.txt
  9.  
  10. my $target;
  11. my %unique;
  12.  
  13. GetOptions( 'table=s' => \$target, );
  14.  
  15. open(INFILE, $target) or die("ERROR: $!\n");
  16.  
  17. while (<INFILE>) {
  18.     chomp;
  19.  
  20.     if (/^\w+/) {
  21.         my($feat, $pval) = split(/\t/, $_ );
  22.         comphash( $feat, $pval, \%unique );
  23.     }
  24. }
  25.  
  26. sub comphash {
  27.     my ( $feat, $pval, $unique_ref ) = @_;
  28.  
  29.     if ( not defined $unique_ref->{$feat}  or  $unique_ref->{$feat} > $pval ) {
  30.         $unique_ref->{$feat} = $pval;
  31.     }
  32. }
  33.  
  34.  
  35. open  SALIDA, '>hash_order.txt' or die "ERROR: $!\n";
  36. for my $feat (sort keys %unique) {
  37.     print SALIDA "$feat\t $unique{$feat}\n";
  38. }
  39. close SALIDA;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Esta es una versión más corta:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use v5.14;
  3. use autodie;
  4.  
  5. # usage: perl /path_to/hash_order.pl /path_to/file.txt
  6.  
  7. my %unique;
  8.  
  9. while (<>) {
  10.     chomp;
  11.     my($feat, $pval) = split;
  12.  
  13.     $unique{$feat} = $pval
  14.         if  not defined $unique{$feat}
  15.         or  $unique{$feat} > $pval
  16.     ;
  17. }
  18.  
  19. open  SALIDA, '>', 'hash_order.txt';
  20. while (my($feat, $pval) = each %unique) {
  21.     say SALIDA "$feat\t$pval";
  22. }
  23. close SALIDA;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
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

Re: Filtrar lista usando hashes

Notapor Alfumao » 2013-01-04 03:13 @176

Una vez más,

¡Muchas gracias, explorer!
Funciona correctamente.

;)
Alfumao
Perlero nuevo
Perlero nuevo
 
Mensajes: 178
Registrado: 2009-12-10 11:20 @514


Volver a Básico

¿Quién está conectado?

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