2012-05-01 1 views
1

ヌクレオチドの出現数(文字列中の文字 'A、T、G、C')を数えたいと思います。私はこのためにtr///演算子を使用しようとしましたが、以下のコードで毎回0のカウントを返します。tr ///演算子の変数を使ってパターンの数を数える方法は?

これは、tr///演算子の内部で変数を使用する場合にのみ発生します。個々の文字を別々に入力すると機能します。私は、パターンマッチング(およびカウント)のためにtr///オペレータの中の変数を使用できるかどうかを知りたかったのです。私たちができるなら、コードを修正する方法を教えてくれる人もいます。

後で私はコドンの数をカウントする予定です(〜64)。したがって、トラブル。あなたの時間を感謝します。ありがとう!

#!/usr/bin/perl 

use strict; 
use warnings; 

my $orf = "ATGCTAGCTAGCATAGAGCTAGCTA"; 
my @atgc = qw(A T G C); 
my %hash =(); 

foreach my $nt(@atgc) { 
    $hash{$nt} = ($orf =~ tr/$nt//); 
} 
+0

'/// TR'演算子は文字ごとに動作します。あなたがコドンを数えたいと思っているときは、あなたを助けません。 –

答えて

3
$hash{$nt} = eval "\$orf =~ tr/\Q$nt\E//" 

仕事をする必要があります。たぶん、これは最も効果的な解決策ではないでしょう。

+0

助けてくれてありがとう。あなたは$ ORFの前にバックスラッシュを使った理由を教えていただけますか? – Jordan

+0

二重引用符で囲まれた文字列を補間した後に有効なPerlコードを取得する。 –

4

"$"、 "n" または "t" のインスタンスは、このようにtrが正しくゼロを返し、 "ATGCTAGCTAGCATAGAGCTAGCTA" ではありません。

tr///演算子を作成する場合は、演算子を解析してコンパイルする必要があります。

my %counts; 
for my $nt (@atgc) { 
    $counts{$nt} = eval "\$orf =~ tr/\Q$nt\E//"; 
} 

しかし、tr///は使用しません。

my %atgc = map { $_ => 1 } @atgc; 
my %counts; 
++$counts{$nt} for grep $atgc{$_}, split //, $orf; 
4

残念ながら、Perlはtr///の検索リストに変数を補間しません。それが表示されることとして - - 一般的な解決策これがない

用心

use strict; 
use warnings; 

my $orf = "ATGCTAGCTAGCATAGAGCTAGCTA"; 
my @atgc = qw(A T G C); 
my %count; 

$count{$1}++ while $orf =~ /([@atgc])/g; 

printf "%s => %d\n", $_, $count{$_} for @atgc; 

出力

A => 8 
T => 6 
G => 6 
C => 5 

:あなたの代わりに正規表現を使用する必要があります文字列の配列のいずれかと一致するかどうかを判定します。何が起こっているのは@atcg二重引用符の文字列のように正規表現に補間されていることです。つまり、Perlはに相当する文字列に変換するために、$"組み込み変数(デフォルトでは単一のスペースに設定されています)を使用します。

ので、コードが実際に

スペースなどの文字にマッチします、と@atgc^]または-のような正規表現文字クラス内の特殊であるものが含まれている場合は、完全に壊れる可能性
$count{$1}++ while $orf =~ /([A T G C])/g; 

のように見えます。

不必要にスペースを数えることは問題ではありませんが、リストにシンボルが含まれている場合は、使用するべき解決策ではありません。

すべてのASCII文字のカウントが

$count{$1}++ while $orf =~ /(.)/sg; 

として安全に書くことができると%countハッシュ内の不要な情報を単に無視することができます。

+2

これは、入力内のスペースもカウントします。あなたが ''^'"、 '"] "または" '' - "を" @ atgc "に持つと、それはうんざりします。 – ikegami

+0

コードを使用すると、実際には4の倍数ですべてが得られます。 – Jordan

+0

@Anish: 'foreach'ループ全体をそのコード行に置き換える必要があります。私のソリューションは独自のものです。私はこれをより明確に示すために私の答えを更新しました。 – Borodin

1

あなたはs///g使用することもできます。ソース文字列は、本当に長いことになるだろうされている場合は、しばらくの内容を保持しているとしてそれを扱い、1を読むことができる

--- 
A: 8 
C: 5 
G: 6 
T: 6

#!/usr/bin/env perl 

use strict; use warnings; 

my $orf = "ATGCTAGCTAGCATAGAGCTAGCTA"; 
my @atgc = qw(A T G C); 

my %hash = map {$_ => $orf =~ s/$_/$_/g } @atgc; 

出力を文字がASCIIであることが保証されていると仮定して、一度に1バイトずつ。あなたは単なる文字列を歩く必要があり、これを行うために、正規表現などを必要としない

#!/usr/bin/env perl 

use strict; use warnings; 

my $orf = "ATGCTAGCTAGCATAGAGCTAGCTA"; 
my %atgc = map { $_ => undef } qw(A T G C); 

use YAML; 
print Dump count(\$orf, \%atgc); 

sub count { 
    my $src_ref = shift; 
    my $lookup = shift; 

    my %count; 

    open my $src, '<', $src_ref or die $!; 
    { 
     local $/ = \1; 
     exists $lookup->{$_} and $count{ $_ } += 1 while <$src>; 
    } 
    close $src; 

    return \%count; 
} 
1

パターンコンパイラを作ります。 quotemeta

sub make_counter { 
    my @sequences = @_; 

    my $pattern = "(?:" . join("|", map quotemeta, @sequences) . ")"; 

    my $compiled = eval q< 
    sub { 
     local($_) = @_; 
     my $n =() = /$pattern/g; 
    } 
    >; 

    if (defined $compiled) { 
    return $compiled; 
    } 
    else { 
    die "$0: internal: counter compilation failed:\[email protected]\n"; 
    } 
} 

、我々は特別な意味で自分に合うようにシーケンス内のすべての文字を強制します。マッチをカウントするためのファンキーなビットというSection 4 of the Perl FAQを説明します。

別のバージョンがリストコンテキストでグローバルに一致したものを使用し、その後、試合の数のカウントを生成、スカラーに結果を割り当てます。

$count =() = $string =~ /-\d+/g; 

それはあなたの順序で迷惑メールを許容することに注意してください。例えば、

my @nucleotides = qw/ G A T C /; 

my $numnuc = make_counter @nucleotides; 
print $numnuc->("xGxAxTxxxxTyA1C2A"), "\n"; 

出力でヌクレオチドを数える:

7

カウントコドンを

my @codons = qw(
    TTT TCT TAT TGT TTC TCC TAC TGC TTA TCA TAA TGA 
    TTG TCG TAG TGG CTT CCT CAT CGT CTC CCC CAC CGC 
    CTA CCA CAA CGA CTG CCG CAG CGG ATT ACT AAT AGT 
    ATC ACC AAC AGC ATA ACA AAA AGA ATG ACG AAG AGG 
    GTT GCT GAT GGT GTC GCC GAC GGC GTA GCA GAA GGA 
    GTG GCG GAG GGG 
); 

my $numcod = make_counter @codons; 
print $numcod->("GAG-GGG!AGG,TAT#TTT"); 

注意して任意のジャンクは、存在する場合、間コドン配列が起こらなければならないこと。

出力:

5
関連する問題