[bcn-pm] Duda con arrays

Salvador Fandiño sfandino a gmail.com
dll feb 2 13:42:11 PST 2015


On 02/02/2015 08:58 PM, Verónica Olmos González wrote:
> ¡Hola a todos!
>
> Bueno, ante todo, como decía en mi presentación, soy bastante (muy) 
> novata en Perl, así que es bastante probable que la esté liando con 
> algo muy básico... pero me gustaría compartir mi problema con 
> vosotros, por si alguno supiera darme alguna orientación (aunque sea 
> simplemente remitirme a alguna página concreta de documentación).
>
> El contexto de mi problema es el siguiente: parto de un array que 
> contiene secuencias de nucleótidos (o sea, strings que deben estar 
> formados por "A", "C", "G" o "T"). La cosa es que estos strings pueden 
> contener, cualquiera de ellos, en determinada posición, el carácter 
> "N", que no es "válido". Lo que hace el resto de mi programa es hacer 
> comparaciones dos a dos entre cada elemento del array. Lo que quiero 
> hacer, y el quid de mi duda: si en "x" posición de cualquier elemento 
> encuentro una "N", debo borrar esa "x-ésima" posición en TODOS los 
> elementos del array. Un ejemplo: si tengo @arr = ("AATN", "AATG", 
> "TATG") debo quedarme con @arr2 = ("AAT", "AAT", "TAT").
>
> Sin enrollarme con más explicaciones, os enseño el código con mi 
> planteamiento:
>
>     @sequences = ("AATGTCAACGAN", "AATGTCAACGNA", "ATTGTCAACGTN",
>     "ATTGTGATCGTT");
>     for ($i = 0; $i <= scalar(@sequences); $i++) {
>         if ($sequences[$i] =~ "N") {
>
>     # Localizo las "N" y guardo su posición en un array
>
>         push(@pos,index($sequences[$i], "N"));
>         }
>     }
>
>     # Elimino posiciones repetidas y ordeno los valores
>     my @pos = do { my %seen; grep { !$seen{$_}++ } @pos };
>     @pos = sort @pos;
>
>     # Mi idea era, mediante expresiones regulares, poner "N" en todos
>     los elementos de los arrays, en las posiciones guardadas, para
>     luego eliminarlo todo evitando "corrimientos" en las posiciones
>
>     for ($i = 0; $i <= scalar(@sequences); $i++) {
>     for ($j = 0; $j <= scalar(@pos); $j++) {
>         substr($sequences[$i],$pos[$j],1) =~ s/\D/N/;
>         }
>     }
>
> Ahora bien, en el último bucle se me va todo de madre, permanece 
> iterando continuamente.
>
> La verdad es que seguro que estoy haciendo fatal algo tontísimo, pero 
> no soy capaz de ver el origen del error, por lo que agradecería 
> enormemente cualquier tipo de orientación.
>
>
> Un saludo,
> Verónica
>

Para esto de la N hay un truco.

Si te fijas, de todos los caracteres AGCTN solo la N tiene un 1 en el 
bit 3 (0x08) asi que puedes detectar donde hay Ns haciendo un OR de 
todas las sequencias y luego buscando los caracteres que tienen ese bit 
a uno en el resultado.

A partir de ahi es fácil generar una mascara que al hacer AND con las 
secuencias originales ponga a cero las posiciones con N, y luego solo 
hay que borrar los ceros:

   @sequences = ("AATGTCAACGAN",
                 "AATGTCAACGNA",
                 "ATTGTCAACGTN",
                 "ATTGTGATCGTT");

   my $mask = '';
   $mask |= $_ for @sequences;
   $mask =~ s/(.)/(ord($1) & 8) ? "\0" : "\xFF"/ge;

   for (@sequences) {
       $_ &= $mask;
       tr/\0//;
   }

   use Data::Dumper;
   print Dumper \@sequences;


------------ pr�a parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://mail.pm.org/pipermail/barcelona-pm/attachments/20150202/34468deb/attachment.html>


Més informació sobre la llista de correu Barcelona-pm