• Publicidad

Problema con archivo dividido en filas y columnas

Perl aplicado a la bioinformática

Problema con archivo dividido en filas y columnas

Notapor alondra » 2010-08-09 13:51 @619

¡Hola!

El siguiente código se corresponde a un programa que estoy intentando hacer para que, dado un archivo dividido en filas y columnas, al introducir el valor contenido en alguna de las columnas me dé el valor de otra columna pero de la misma fila. Por ejemplo:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
Pedro     23     Madrid
Juan      12     Sevilla
Lucía     28     Jaén
...
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Lo que quiero es que al pedirme el programa el nombre de una ciudad y escribir Jaén, me imprima por pantalla "Lucía". Mi problema es que este código solo me sirve para la primera línea del archivo.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2.  
  3. use strict;
  4.  
  5. use warnings;
  6.  
  7.  
  8.  
  9. open( ARCHIVO, 'file.gff' );
  10.  
  11. @archivo = <ARCHIVO>;
  12.  
  13. close(ARCHIVO);
  14.  
  15.  
  16.  
  17. my $nombre = '';
  18.  
  19.  
  20.  
  21. print "Deme un nombre: ";
  22.  
  23. $nombre = <STDIN>;
  24.  
  25. chop $nombre;
  26.  
  27.  
  28.  
  29. foreach $linea (@archivo) {
  30.  
  31.     @campo =
  32.  
  33.       split( /\t/, $linea ); #esto lo hago para sacar cada una de las 9 columnas
  34.  
  35.                              #del fichero, que está separadas por tabuladores
  36.  
  37.  
  38.  
  39.     #el campo[8], que equivale a la última columna, está dividido en 3 partes separadas por ";"
  40.  
  41.     foreach $linea ( $campo[8] ) {
  42.  
  43.         @nombres = split( /;/, $linea );    #esto lo hago para obtener cada una de esas partes
  44.  
  45.  
  46.  
  47.         while ( $nombre ne 'fin' ) {
  48.  
  49.  
  50.  
  51.             #para que el nombre que yo introduzca por pantalla esté en el archivo,
  52.  
  53.             #es decir, para que me encuentre la coincidencia, hago lo siguiente:
  54.  
  55.  
  56.  
  57.             if ( $nombre eq "$nombres[0]" ) {
  58.  
  59.                 print "El gen $nombre se encuentra en el lugar $campo[0],\n";
  60.  
  61.  
  62.  
  63.             }
  64.  
  65.             else {
  66.  
  67.                 print "no existe";
  68.  
  69.             }
  70.  
  71.  
  72.  
  73.             print "\n Deme un nombre:\n";
  74.  
  75.             $nombre = <STDIN>;
  76.  
  77.             chop $nombre;
  78.  
  79.         }
  80.  
  81.     }
  82.  
  83. }
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4
alondra
Perlero nuevo
Perlero nuevo
 
Mensajes: 2
Registrado: 2010-08-09 08:27 @394

Publicidad

Re: Problema con archivo dividido en filas y columnas

Notapor explorer » 2010-08-09 18:15 @802

Bienvenida a los foros de Perl en Español, alondra.

Realmente, no necesitas, para nada, guardar la información en un array de dos dimensiones. ¿Por qué? Pues porque puedes realizar la búsqueda de la información sin guardar nada, simplemente ir leyendo línea a línea el fichero de entrada.

Más detalle:
1.- Preguntas al usuario qué es lo que quieres buscar
2.- Abres el fichero
3.- Bucle por todas las filas. Por cada fila...
4.- Extraemos los campos que nos interesan, desde la fila
5.- Si la fila contiene lo que queremos, imprimimos el resultado
6.- Terminamos (si sabemos que no hay más filas con los mismos datos de búsqueda), o seguimos con la siguiente fila.

Otra cosa es si quieres que el usuario busque más de una vez. Entonces sí que merece la pena guardar la información. Pero aún así, tampoco necesitas crear un array de dos dimensiones. Te vale con guardar las filas del fichero de la misma manera en que lo haces ahora, en el array @archivo. Por lo tanto, quedaría así.

1.- Leer el fichero, en filas, al array @fichero
2.- Bucle, mientras que el cliente no marque el final
3.- Leemos lo que quiere buscar
4.- Repetimos el bucle descrito antes, por el array @archivo
5.- Lo demás, igual.
6.- Volvemos al 2.

Aún así, si quieres guardar la información en un array multidimensional, debes entender cómo crearlos y manejarlos. En perldoc perllol tienes una explicación de cómo entenderlos. El problema es que, si no se tiene cuidado, la sintaxis de Perl puede asustar bastante. Y también hay que prestar atención a los detalles.

Esta es una forma de crear una matriz de dos por dos elementos:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my @matriz = (
    [ 1, 2 ],
    [ 3, 4 ],
);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Ahora puedes acceder al primer elemento de la segunda fila:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
print $matriz[1]->[0];
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

El operador flecha, cuando está entre [] y {}, se puede obviar, así que podemos dejarlo en
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
print $matriz[1][0];
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

que entonces se parece mucho a la sintaxis del lenguaje C. Necesitamos seguir poniendo el '$' delante porque estamos recuperando un solo elemento, no varios.

Decía que hay que prestar atención a los detalles. La definición del array lo hemos hecho, primero, usando paréntesis, porque, efectivamente, estamos creando un array. Pero luego, dentro, estamos usando corchetes. Cada par de ellos, está creando un nuevo array anónimo (no tiene nombre), del que Perl obtiene su referencia, que es al final, lo que se almacena en el array. Por eso se dice que un array de arrays es, en realidad, un array de referencias a arrays. Esto es exactamente lo que también se hace en C.

Ahora que tenemos un array, podemos, por ejemplo, agregarle una nueva línea:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
push @matriz, [ 5, 6 ];
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Usamos push(), para agregar un nuevo elemento a un array. Y ese elemento es una referencia a un nuevo array (los corchetes) que tiene dos elementos.

En cuanto a tu programa, hay varios errores:
* las líneas 41 y 43 deberían estar al revés: primera partes el último campo, y luego recorres sus valores
* las líneas que preguntan al usuario por lo que quieren buscar deben estar fuera del bucle que recorre las líneas, porque entonces pasa lo que dices: que solo ha encontrado la información de la primera línea
* por último, hay un problema, mucho más grave, si los datos contienen acentos, pero como veo en el código que se trata de genes, no creo que exista ese problema.

Una solución podría ser esta:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. open(ARCHIVO, 'file.gff');
  6. my @archivo = <ARCHIVO>;
  7. close(ARCHIVO);
  8.  
  9. chomp(@archivo);                                     # quitamos los finales de línea
  10.  
  11. my $que_buscamos = '';
  12.  
  13. do {
  14.     if ($que_buscamos) {                             # si hay algo que buscar...
  15.         for my $linea (@archivo) {                   # para todas las líneas del @archivo
  16.             my @campos  = split( /\t/, $linea );     # dividir en campos
  17.             my @nombres = split( /;/,  $campos[-1]); # dividir último campo
  18.  
  19.             for my $nombre (@nombres) {              # recorremos los nombres
  20.                 if ($nombre eq $que_buscamos) {
  21.                     print "El gen $nombre se encuentra en el lugar $campos[0]\n";
  22.                 }
  23.             }
  24.         }
  25.     }
  26.  
  27.     print "Deme un nombre: ";
  28.     $que_buscamos = <STDIN>;
  29.     chomp $que_buscamos;
  30.  
  31. } while ($que_buscamos ne 'fin');
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Pero esto lo que hace es extraer la información de las líneas cada vez que queremos buscar algo. Lo mejor es guardar la información en un array:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. open(ARCHIVO, 'file.gff');
  6. my @archivo = <ARCHIVO>;
  7. close(ARCHIVO);
  8.  
  9. chomp @archivo;
  10.  
  11. my @lineas;
  12.  
  13. foreach my $linea (@archivo) {
  14.     my @campos  = split( /\t/, $linea );    # 9 columnas
  15.  
  16.     push @lineas, [ @campos ];
  17. }
  18.  
  19. #use Data::Dumper;
  20. #print Dumper \@lineas;
  21.  
  22. my $que_buscamos = '';
  23.  
  24. do {
  25.     if ($que_buscamos) {                                # si hay algo que buscar...
  26.         for my $linea (@lineas) {                       # para todas las líneas...
  27.  
  28.             my @nombres = split( /;/,  $linea->[-1]);   # dividimos el último campo
  29.  
  30.             for my $nombre (@nombres) {                 # recorremos los nombres
  31.                 if ($nombre eq $que_buscamos) {
  32.                     print "El gen $nombre se encuentra en el lugar $linea->[0]\n";
  33.                 }
  34.             }
  35.         }
  36.     }
  37.  
  38.     print "Deme un nombre: ";
  39.     $que_buscamos = <STDIN>;
  40.     chomp $que_buscamos;
  41.  
  42. } while ($que_buscamos ne 'fin');
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

En este caso, estamos creando un array bidimensional. En @lineas guardamos, con push(), una línea cada vez, y en esa línea guardamos un único elemento: una referencia a un array anónimo, que a su vez contiene todos los @campos de la $linea leída.

Ahora bien... la búsqueda también lo podemos hacer con expresiones regulares, pues lo que buscamos es un nombre dentro de otros tres. Solo nos interesa saber si está o no.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. open(ARCHIVO, 'file.gff');
  6. my @archivo = <ARCHIVO>;
  7. close(ARCHIVO);
  8.  
  9. chomp @archivo;
  10.  
  11. my @lineas;
  12.  
  13. foreach my $linea (@archivo) {
  14.     my @campos  = split( /\t/, $linea );
  15.  
  16.     push @lineas, [ @campos ];
  17. }
  18.  
  19. #use Data::Dumper;
  20. #print Dumper \@lineas;
  21.  
  22. my $que_buscamos = '';
  23.  
  24. do {
  25.     if ($que_buscamos) {                        # si hay algo que buscar...
  26.         for my $linea (@lineas) {               # para todas las líneas...
  27.             if ($linea->[-1] =~ /$que_buscamos/) {  # si el último campo contiene lo $que_buscamos
  28.                 print "El gen $que_buscamos se encuentra en el lugar $linea->[0]\n";
  29.             }
  30.         }
  31.     }
  32.  
  33.     print "Deme un nombre: ";
  34.     $que_buscamos = <STDIN>;
  35.     chomp $que_buscamos;
  36.  
  37. } while ($que_buscamos ne 'fin');
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: Problema con archivo dividido en filas y columnas

Notapor alondra » 2010-08-11 08:09 @381

Muchas gracias !Ya funciona!
alondra
Perlero nuevo
Perlero nuevo
 
Mensajes: 2
Registrado: 2010-08-09 08:27 @394


Volver a Bioinformática

¿Quién está conectado?

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

cron