Как переписать однострочный код (или меньше строкового кода в командной строке) этого кода в Perl? - PullRequest
1 голос
/ 23 марта 2011

У меня есть такой код:

#!/usr/bin/perl
use strict;
use warnings;      
my %proteins = qw/
    UUU F UUC F UUA L UUG L UCU S UCC S UCA S UCG S UAU Y UAC Y UGU C UGC C UGG W
    CUU L CUC L CUA L CUG L CCU P CCC P CCA P CCG P CAU H CAC H CAA Q CAG Q CGU R CGC R CGA R CGG R
    AUU I AUC I AUA I AUG M ACU T ACC T ACA T ACG T AAU N AAC N AAA K AAG K AGU S AGC S AGA R AGG R
    GUU V GUC V GUA V GUG V GCU A GCC A GCA A GCG A GAU D GAC D GAA E GAG E GGU G GGC G GGA G GGG G
    /;
open(INPUT,"<dna.txt");
while (<INPUT>) {    
    tr/[a,c,g,t]/[A,C,G,T]/;
    y/GCTA/CGAU/;    
    foreach my $protein (/(...)/g) {
        if (defined $proteins{$protein}) {
        print $proteins{$protein};
        }
}
}
close(INPUT);

Этот код связан с ответом на мой другой вопрос: ДНК в РНК и получение белков с помощью Perl

TheВывод программы:

SIMQNISGREAT

Как я могу переписать этот код с помощью Perl, он будет работать в командной строке и будет перезаписан с меньшим количеством кода (если возможно, однострочный код)?

PS 1: dna.txt выглядит так:

TCATAATACGTTTTGTATTCGCCAGCGCTTCGGTGT

PS 2: Если код будет меньше строки, то принято писатьmy %proteins переменная в файл.

Ответы [ 5 ]

3 голосов
/ 23 марта 2011

Единственные изменения, которые я бы порекомендовал сделать, - это упростить цикл while:

while (<INPUT>) {
    tr/acgt/ACGT/;
    tr/GCTA/CGAU/;
    foreach my $protein (/(...)/g) {
        if (defined $proteins{$protein}) {
            print $proteins{$protein};
        }
    }
}

Поскольку y и tr являются синонимами, вы должны использовать только один из них.Я думаю, что tr читается лучше, чем y, поэтому я выбрал tr.Кроме того, вы называли их совершенно по-разному, но это должно быть таким же эффектом и упоминать только те буквы, которые вы на самом деле изменили.(Все остальные символы были транспонированы для себя. Это делает намного труднее увидеть, что на самом деле меняется.)

Возможно, вы захотите удалить open(INPUT,"<dna.txt"); и соответствующий close(INPUT); линии, поскольку они значительно затрудняют использование вашей программы в конвейерах оболочки или с другими входными файлами.Но это зависит от вас, если входной файл будет всегда , будет dna.txt и никогда ничего другого, это нормально.

2 голосов
/ 24 марта 2011

Кто-то (@kamaci) назвал мое имя в другой ветке.Это лучшее, что я могу придумать, сохраняя таблицу белков в командной строке:

perl -nE'say+map+substr("FYVDINLHL%VEMKLQL%VEIKLQFYVDINLHCSGASTRPWSGARTRP%SGARTRPCSGASTR",(s/GGG/GGC/i,vec($_,0,32)&101058048)%63,1),/.../g' dna.txt

(Оболочка для цитирования, для Windows - символы свопинга ' и ").Эта версия помечает недопустимые кодоны %, вы, вероятно, можете это исправить, добавив =~y/%//d в соответствующее место.

Подсказка: это выбирает 6 битов из необработанного кодирования ASCII тройки РНК, давая 64коды от 0 до 101058048;чтобы получить индекс строки, я уменьшаю результат по модулю 63, но это создает одно двойное отображение, которое, к сожалению, должно было кодировать два разных белка.s/GGG/GGC/i отображает один из них в другой, кодирующий нужный белок.

Также обратите внимание на круглые скобки перед оператором %, который оба изолирует оператор , от списка аргументовsubstr и исправляют приоритет & против %.Если вы когда-либо используете это в рабочем коде, вы плохой, плохой человек.

2 голосов
/ 23 марта 2011
#!/usr/bin/perl
%p=qw/UUU F UUC F UUA L UUG L UCU S UCC S UCA S UCG S UAU Y UAC Y UGU C UGC C UGG W
CUU L CUC L CUA L CUG L CCU P CCC P CCA P CCG P CAU H CAC H CAA Q CAG Q CGU R CGC R CGA R CGG R
AUU I AUC I AUA I AUG M ACU T ACC T ACA T ACG T AAU N AAC N AAA K AAG K AGU S AGC S AGA R AGG R
GUU V GUC V GUA V GUG V GCU A GCC A GCA A GCG A GAU D GAC D GAA E GAG E GGU G GGC G GGA G GGG G/;
$_=uc<DATA>;y/GCTA/CGAU/;map{print if$_=$p{$_}}/(...)/g
__DATA__
TCATAATACGTTTTGTATTCGCCAGCGCTTCGGTGT

Фу.Лучшее, что я могу придумать, по крайней мере, это быстро.Если вы уверены, что ввод всегда находится в верхнем регистре, вы также можете сбросить uc, сохранив еще два символа.Или, если ввод всегда один и тот же, вы могли бы сразу присвоить его $_ вместо того, чтобы читать его из любого места.

Полагаю, мне не нужно говорить, что этот код должен не для использования в производственных условиях или где-либо еще, кроме чистого удовольствия.При реальном программировании читаемость почти всегда выигрывает у компактности.

Несколько других версий, которые я упоминал в комментариях:

Чтение% p и ДНК из файлов:

#!/usr/bin/perl
open A,"<p.txt";map{map{/(...)/;$p{$1}=chop}/(... .)/g}<A>;
open B,"<dna.txt";$_=uc<B>;y/GCTA/CGAU/;map{print if$_=$p{$_}}/(...)/g

Из оболочки с perl -e:

perl -e 'open A,"<p.txt";map{map{/(...)/;$p{$1}=chop}/(... .)/g}<A>;open B,"<dna.txt";$_=uc<B>;y/GCTA/CGAU/;map{print if$_=$p{$_}}/(...)/g'
1 голос
/ 23 марта 2011

На большинство вещей уже было указано, особенно на то, что читаемость имеет значение.Я бы не стал сокращать программу больше, чем следует.

use strict;
use warnings;
# /4188260/kak-perepisat-odnostrochnyi-kod-ili-menshe-strokovogo-koda-v-komandnoi-stroke-etogo-koda-v-perl
my $fnprot = shift || 'proteins.txt';
my $fndna  = shift || 'dna.txt';
# build protein table
open my $fhprot, '<', $fnprot or die "open $fnprot: $!";
my %proteins = split /\s+/, do { local $/; <$fhprot> };
close $fhprot;
# process dna data
my @result;
open my $fhdna, '<', $fndna or die "open $fndna: $!";
while (<$fhdna>) {
    tr/acgt/ACGT/;
    tr/GCTA/CGAU/;
    push @result, map $proteins{$_}, grep defined $proteins{$_}, m/(...)/g;
}
close $fhdna;
# check correctness of result (given input as per original post)
my $expected = 'SIMQNISGREAT';
my $got = join '', @result;
die "@result is not expected" if $got ne $expected;
print "@result - $got\n";

Единственное, что я добавил в одну строку, это push map grep m//g в цикле while.Обратите внимание, что в Perl 5.10 добавлен оператор «определен или» - //, который позволяет писать:

push @result, map $proteins{$_} // (), m/(...)/g;

Хорошо, идиома open do local $/ file slurp удобна для удаления небольших файлов в память.Надеюсь, вы найдете это немного вдохновляющим.: -)

0 голосов
/ 28 ноября 2013

Если записать данные белков в другой файл с пробелом без разрыва строки.Таким образом, вы можете импортировать данные, прочитав файл один раз.

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

open(INPUT, "<mydata.txt");
open(DATA, "<proteins.txt");
my %proteins = split(" ",<DATA>);

while (<INPUT>) {
    tr/GCTA/CGAU/;
    while(/(\w{3})/gi) {print $proteins{$1} if (exists($proteins{$1}))};
}
close(INPUT);
close(DATA);

Вы можете удалить строку кода " tr / a, c, g, t / A, C, G,T / ", потому что у оператора совпадения есть опция без учета регистра (опция i ).И оригинальный цикл foreach можно оптимизировать, как в коде выше. $ 1 переменная здесь - это результат сопоставленного шаблона в скобках операции сопоставления / (\ w {3}) / gi

...