• Publicidad

Se machacan los datos en el hash

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

Se machacan los datos en el hash

Notapor Javier_UPO » 2020-06-18 13:07 @588

Tenemos un problema: queremos extraer una serie de columnas de un archivo txt el cual consta de 5 columnas. Queremos quedarnos con la columna 1, 3 y 5.

Sin embargo, tras crear el hash en el while y hacer la consulta con el STDIN, no hay resultado alguno, ya que solo guarda la última línea del txt.

Necesitamos ayuda urgente, ya que es para un trabajo de una asignatura del grado. ¡¡¡Un saludo!!!

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use warnings;
  3. use strict;
  4.  
  5. my $archivo = $ARGV[0];
  6. my @campos;
  7. my @identificadores;
  8. my %datos;
  9. my @array;
  10. my @array2;
  11.  
  12. # Hemos declarado las variables y diccionarios fuera del bucle
  13. open( IN, $archivo ) or die "No se pudo leer $archivo, programa erróneo.";
  14. while (<IN>) {
  15.  
  16.     # eliminar el salto de línea
  17.     chomp $_;
  18.  
  19.     # cortar los elementos separados por un tabulador y añadirlo cada uno como  elemento de un array
  20.     @campos          = split( '\t', $_ );
  21.     @identificadores = split( ',',  $campos[4] );
  22.  
  23.     # creamos un hash con valores separados por espacios del array @campos
  24.     #%datos = ("$campos[2]" => "$campos[0] $campos[4]");
  25.     push( @array,  "$campos[2]" );
  26.     push( @array2, "$campos[0] $campos[4]" );
  27.  
  28.     #print ($datos {"$campos[2]"}. "\n");
  29. }
  30.  
  31. # Como sólo nos estaba almacenando en el diccionario el último valor, hemos creado unos arrays para almacenar los datos
  32. for ( my $c = 0; $c <= 2306; $c++ ) {
  33.     %datos = ( "$array[$c]" => "$array2[$c]" );
  34.  
  35.     #print ($datos {"$array[$c]"}. "\n");
  36. }
  37.  
  38. # Introducimos una especie en la terminal
  39. print( "Introduzca especie" . "\n" );
  40. my $in = (<STDIN>);
  41. chomp($in);
  42.  
  43. #Si la especie no coincide con el formato del nombre científico, que retorne un error
  44. #if ($in !~ m/[a-z] [a-z]/) {
  45. #print("Error. Esto no es una especie\n");
  46. #}
  47. # Búsqueda en el hash de nuestra especie con un bucle foreach y que te devuelva
  48. #los campos Identificador y Bases de datos correspondientes a la especie
  49. # Aquí es dónde tenemos el problema: Al ejecutar el script en la terminal, nos permite introducir
  50. # la especie con el STDIN, pero no nos da ningún dato en la terminal.
  51. foreach my $busqueda ( keys %datos ) {
  52.     if ( $busqueda =~ m/$in/i ) {
  53.         print( $datos {"$in"} . "\n" );
  54.     }
  55. }
  56. close IN;
  57.  
Coloreado en 0.006 segundos, usando GeSHi 1.0.8.4
Javier_UPO
Perlero nuevo
Perlero nuevo
 
Mensajes: 2
Registrado: 2020-06-18 12:38 @568

Publicidad

Re: Se machacan los datos en el hash

Notapor explorer » 2020-06-18 20:08 @881

El error está en la línea 33:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.     %datos = ( "$array[$c]" => "$array2[$c]" );
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

En esa línea estás redefiniendo el hash %datos en cada vuelta, por lo que solo guarda, al final, la última línea.

Mejor así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.     $datos{ $array[$c] } = $array2[$c];
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: Se machacan los datos en el hash

Notapor Javier_UPO » 2020-06-19 05:01 @250

Muchas gracias por la ayuda. Ahora el hash sí imprime los resultado de mi búsqueda STDIN.

Sin embargo surgió un problema, ya que en nuestro archivo txt hay Especies que se repiten.

Al hacer la búsqueda del termino STDIN, por ejemplo, Blastococcus saxobsidens, deberían salir 2 resultados, pero solo nos imprime los datos de uno de ellos. Te adjunto script por si nos puedes ayudar. ¡¡ Bendito foro de Perl !!

#!/usr/bin/perl
use warnings;
use strict;

my $archivo = $ARGV[0];
my @campos;
my @identificadores;
my %datos;
my @array;
my @array2;

# Hemos declarado las variables y diccionarios fuera del bucle
open( IN, $archivo ) or die "No se pudo leer $archivo, programa erróneo.";
while (<IN>) {

# eliminar el salto de línea
chomp $_;

# cortar los elementos separados por un tabulador y añadirlo cada uno como elemento de un array
@campos = split( '\t', $_ );
@identificadores = split( ',', $campos[4] );

# creamos un hash con valores separados por espacios del array @campos
#%datos = ("$campos[2]" => "$campos[0] $campos[4]");
push( @array, "$campos[2]" );
push( @array2, "Identificador: $campos[0]\nBases de datos: $campos[4]\n");

#print ($datos {"$campos[2]"}. "\n");
}

# Como sólo nos estaba almacenando en el diccionario el último valor, hemos creado unos arrays para almacenar los datos
for (my $c = 0; $c <= 2305; $c++ ) {
$datos {$array[$c]} = $array2[$c];

print ($datos {"$array[$c]"}. "\n");
}

# Introducimos una especie en la terminal
print( "Introduzca especie" . "\n" );
my $in = (<STDIN>);
chomp($in);

#Si la especie no coincide con el formato del nombre científico, que retorne un error
if ($in !~ m/[a-z+] [a-z+]/i) {
print("Error. Esto no es una especie\n");
}
# Búsqueda en el hash de nuestra especie con un bucle foreach y que te devuelva
#los campos Identificador y Bases de datos correspondientes a la especie
# Aquí es dónde tenemos el problema: Al ejecutar el script en la terminal, nos permite introducir
# la especie con el STDIN, pero solo nos da 1 resultado dato en la terminal. Si la especie se repite más de una vez, solo nos da un resultado.
foreach my $busqueda ( keys %datos ) {
if ( $busqueda =~ m/$in/i ) {
print( $datos {"$in"} . "\n" );
}
}
close IN;
...
Javier_UPO
Perlero nuevo
Perlero nuevo
 
Mensajes: 2
Registrado: 2020-06-18 12:38 @568

Re: Se machacan los datos en el hash

Notapor explorer » 2020-06-19 09:05 @420

La solución es guardar más de un elemento en la parte de "valor" del hash. Y eso se puede conseguir con un array.

Es decir, guardamos como valor un array. Y ese array contendrá elementos, cada uno de los cuales es el valor leído en el archivo. De esa manera guardamos juntos todos los registros que sean de la misma especie.

Algo así (no probado):
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use warnings;
  3. use strict;
  4.  
  5.  
  6. # Declaramos las variables y diccionarios fuera del bucle
  7. my $archivo = $ARGV[0] or die "Uso: $0 <archivo a procesar>\n";
  8. my %datos;
  9.  
  10. # Bucle de lectura
  11. open my $IN, '<', $archivo
  12.     or die "ERROR: No se pudo leer $archivo, programa erróneo.\n";
  13.  
  14. while (<$IN>) {
  15.     chomp;
  16.  
  17.     # Cortar los elementos separados por un tabulador y
  18.     # añadirlo cada uno como  elemento de un array
  19.     my @campos = split /\t/;
  20.  
  21.     # Guardamos la información en el hash %datos
  22.     # Las claves son el nombre de la especie
  23.     # Los valores son agregados a un array que contiene la información
  24.     push @{ $datos{$campos[2]} }, "Identificador: $campos[0]\nBases de datos: $campos[4]\n";
  25. }
  26.  
  27. close $IN;
  28.  
  29. # TODO : Comprobación
  30. use Data::Dumper;
  31. print Dumper \%datos;
  32.  
  33. # Bucle de consulta
  34. while (1) {
  35.     print "Introduzca especie: ";
  36.     my $in = <STDIN>;
  37.     chomp $in;
  38.  
  39.     # Si la especie no coincide con el formato del nombre científico,
  40.     # que retorne un error
  41.     if ($in =~ m/[a-z]+/i) {
  42.         # Búsqueda en el hash de nuestra especie con un bucle foreach y que te devuelva
  43.         # los campos Identificador y Bases de datos correspondientes a la especie.
  44.         for my $busqueda ( keys %datos ) {
  45.             if ( $busqueda =~ m/$in/i ) {
  46.                 for my $valor (@{ $datos{$busqueda} }) {
  47.                     print "$valor\n";
  48.                 }
  49.             }
  50.         }
  51.     }
  52.     else {
  53.         print "Error. Esto no es una especie.\n";
  54.     }
  55. }
  56. __END__
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


Las líneas 29 a 32 las he puesto para que el módulo Data::Dumper vuelque toda la estructura de %datos. Así podréis ver cómo queda lo leído. Una vez que estéis conformes, esas líneas se pueden dejar comentadas, o borrarlas definitivamente.

En perldoc perlreftut tenéis un pequeño tutorial de cómo se construyen y manejan estructuras complejas en Perl.

Edito: había un error en la expresión regular.
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 3 invitados