2014-10-09 18 views
-2

我有以下任務,我想知道如何在Perl中最有效地解決這個問題。 首先,我有66個元素的數組(染色體:開始:結束),看起來像這樣從文本文件中篩選符合Perl中任何數組元素的行

my @array = qw(chr1:1566-1762 chr7:1695-1955 ....) 

接着我有一個大小爲50MB的包含該

CHR \t START \t \END \tab \Pattern 
    chr1 \t 1757 \t \2354 \t XM:Z:......H..H....H 
    . 
    . 

我想要一個文件檢查我的文件的每一行,是否位置,開始和結束符合我的數組中的任何元素。文件中的讀取位置與我的數組中的位置不同,但是開始位置應該包含在範圍內。因此,例如,我有一個適合第一個元素「chr1:1566-1662」的起始位置爲1757的讀數。

您會採取什麼方法?我很高興每一個提示和想法!

+0

因此,如果我理解得很好,您只需要考慮CHR列和START列?你可以編輯你的問題,並添加更多的數據進行一些測試。 – 2014-10-09 14:39:40

+1

您的文件是否實際在每個字段之間包含文字字符'\ t',或者您只是試圖表明它是製表符分隔的? – ThisSuitIsBlackNot 2014-10-09 14:39:45

+0

它是製表符分隔! – user3401516 2014-10-09 19:59:43

回答

1

首先,我將數組從字符串beeing數組改爲某種結構數組(散列)。這使得一些事情變得更加容易:

my @array = (
    { chr => "chr1", start => 1566, end => 1762 }, 
    { chr => "chr7", start => 1695, end => 1955 } 
); 

進一步優化可以(用染色體在範圍列表的哈希鍵)是可以想象的。

然後逐行瀏覽您的文件並分割每一行並使用此信息來檢查。

open FILE, fname || die "could not open file\n"; 

while(my $line = <FILE>){ 
    my @fields = split("\t", $line); 
    chomp($fields[0]); # remove whitespaces 
    my $entry = {chr => $fields[0], start => $fields[1], end => $fields[2]}; 
    foreach $elem(@array){ 
    if(testMatch($entry, $elem)){ 
     print "found something"; 
    } 
    } 
} 

close FILE; 

拆分可能更復雜。你在問題中的例子並不十分清楚它的外觀。

的testMatch日常簡單地返回1,如果條目匹配

sub testMatch 
{ 
    my $elem = shift; 
    my $range = shift; 

    return $elem->{chr} eq $range->{chr} 
     && $elem->{start} >= $range->{start} 
     && $elem->{start} <= $range->{end} 
    # && $elem->{end} <= $range->{end} # not sure if the segment has to be entirely in the range 
    ; 

如果你不想重新格式化您的輸入@array您可以讀取文件之前創建編程方式重新格式化。 }

相關問題