[bcn-pm] Duda con arrays

Daniel Boerner bourbaki007 a gmail.com
dij feb 5 11:34:49 PST 2015


Hola,

he leído el correo tarde (hace dos días). Así que, no sé sí llego tarde con
mis soluciones.

Pero me ha gustado mucho el problema, le he dado un par de vueltas y por sí
aún sirve de algo, ahí van.

Antes, pero, me gustaría saber si la operación que describe el problema
tiene algún nombre en bioinformática o biología? Simple curiosidad. Gracias!

En las dos soluciones propuestas, asumo que la longitud de cada cadena de
entrada es la misma.
He probado cada solución con cuatro entradas diferentes.

1. Mi primera idea consiste en descomponer las cadenas en arrays, formando
un array de arrays (matriz). Traspongo la matriz resultante y elimino de
esta todas las filas que contienen 'N'. El resultado, lo vuelvo a trasponer
y de cada fila formo una nueva cadena (join de cada elemento de la fila).
Estas nuevas cadenas forman el resultado final.

#!/usr/bin/env perl

use strict;
use warnings;
use Data::Dumper;

#my @in = qw( ABCDN ANHYI ABCDE );

#my @in = qw( ABCDN AHYNI ABCDE ABNCD AHNYI EDCBA ANBCD NAHYI CDEBA );

#my @in = qw( ABCDEF GHIJKL MOPQRS );

my @in = qw( CAGGCDGGNACACDACGAG AGCGCDGGNACACDNCGAG ACGGCDGGCACACDACAGG
GACGCDGGADCACDACGGA );

#decompose strings
my @list1;
push @list1, map [ split // ], @in;

print Dumper(\@list1);

#transpose and sieve out
my @list2;
foreach my $j (0 .. $#{$list1[0]}) {
  my $t = [ map $_->[$j], @list1 ];
  next if grep $_ eq 'N', @$t;
  push @list2, $t;
}

print Dumper(\@list2);

#transpose and compose strings
my @list3;
foreach my $j (0 .. $#{$list2[0]}) {
  push @list3, join '', map $_->[$j], @list2;
}

print Dumper(\@list3);

#print result
print "$_\n" foreach @list3;


2. Como segunda solución, mediante un hash acumulo todos los indices en los
que se encuentra una 'N'. Una vez que tengo todos los indices, descompongo
en un array cada cadena (splice) y extraigo con slice todos aquellos
elementos cuyo indice NO se encuentra en el conjunto de indices calculados
anteriormente. Finalmente, vuelvo a construir nuevas cadenas con join a
partir de la descomposición de cada una de ellas.

#!/usr/bin/env perl

use strict;
use warnings;

my @in = qw( ABCDN ANHYI ABCDE );

#my @in = qw( ABCDN AHYNI ABCDE ABNCD AHNYI EDCBA ANBCD NAHYI CDEBA );

#my @in = qw( ABCDEF GHIJKL MOPQRS );

#my @in = qw( CAGGCDGGNACACDACGAG AGCGCDGGNACACDNCGAG ACGGCDGGCACACDACAGG
GACGCDGGADCACDACGGA );

my %m;
foreach ( @in ) {
  $m{ $-[0] }++ while $_ =~ /N/g
};

foreach ( @in ) {
  print join '', (split //)[ grep { not exists $m{$_} } 0 ..
length($in[0])-1 ], "\n";
}


Have fun!


El 3 de febrero de 2015, 11:47, Verónica Olmos González <
volmosg.bt a gmail.com> escribió:

El 3 de febrero de 2015, 11:47, Verónica Olmos González <
volmosg.bt a gmail.com> escribió:

> Muchísimas gracias por las respuestas.
>
> De momento, he probado lo de la máscara que me ha sugerido Salvador (no
> tenía ni idea de que se podía hacer eso) y, salvo porque los elementos del
> array no recuperan so longitud original después de la eliminación (no sé si
> esto es la consecuencia lógica esperable; pero seguiré echándole un ojo),
> me soluciona bastante bien el problema que tenía :)
>
> Lo dicho, muchas gracias, y seguiré investigando con las cosillas que me
> habéis ido diciendo!
>
> El 3 de febrero de 2015, 8:17, H. Daniel Cesario <maneta a gmail.com>
> escribió:
>
> Igual podrías mirar la funcion grep de perl:http://
>> perlmaven.com/filtering-values-with-perl-grep
>> Y filtrar la array de entrada quitando los elementos que no te interesan.
>> Ej:
>> my @arr2 = grep { $_ =~ /(?!N)/ } @arr1;
>>
>> No estoy seguro de la regex(dont shoot the messenger)
>>
>> Pero el grep igual te ayuda!
>>
>> Salut y Perl
>>
>> Sent from my iPhone
>>
>> On 3/2/2015, at 8:00, JJ Merelo <jjmerelo a gmail.com> wrote:
>>
>> Madre mía, qué hack. Aplausos.
>>
>> El 2 de febrero de 2015, 22:42, Salvador Fandiño <sfandino a gmail.com>
>> escribió:
>>
>>>  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;
>>>
>>>
>>>
>>> _______________________________________________
>>> llista dels Barcelona-pm
>>> Barcelona-pm a pm.org
>>> http://mail.pm.org/mailman/listinfo/barcelona-pm
>>> BCN Perl Mongers: http://barcelona.pm.org
>>>
>>
>>
>>
>> --
>> JJ
>>
>> _______________________________________________
>> llista dels Barcelona-pm
>> Barcelona-pm a pm.org
>> http://mail.pm.org/mailman/listinfo/barcelona-pm
>> BCN Perl Mongers: http://barcelona.pm.org
>>
>>
>> _______________________________________________
>> llista dels Barcelona-pm
>> Barcelona-pm a pm.org
>> http://mail.pm.org/mailman/listinfo/barcelona-pm
>> BCN Perl Mongers: http://barcelona.pm.org
>>
>
>
>
> --
> Verónica Olmos González
> Skype: v.olmosg
> Teléfono/Phone: +34 666 68 16 01
>
> _______________________________________________
> llista dels Barcelona-pm
> Barcelona-pm a pm.org
> http://mail.pm.org/mailman/listinfo/barcelona-pm
> BCN Perl Mongers: http://barcelona.pm.org
>
-------------- part següent --------------
Un document HTML ha estat eliminat...
URL: <http://mail.pm.org/pipermail/barcelona-pm/attachments/20150205/1bb4c40f/attachment.html>


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