[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