找到连续范围并从if循环中传递值

时间:2013-09-29 15:53:03

标签: perl

我想找到所有值都大于0.3的连续范围。例如

A   1   10  0.2
A   20  40  0.4
A   60  75  0.5
A   90  100 0.55
A   200 205 0.43
A   211 270 0.8
A   450 511 0.1
A   513 550 0.0
B   1   10  0.6
B   50  200 0.7
B   300 350 0.8
B   400 500 0.9
B   600 711 0.4
B   800 900 0.2

输出:

A   20  270
B   1   711

我试过了:

while(<>){
        chomp($_);
        my @line = split("\t| ", $_);
        my $letter=$line[0];
        my @start;
        my @end;
                if($line[3]>0.3){
                        push (@start, $line[1]);
                        push (@end, $line[2]);

                        }
                if($line[3]<0.3){
                        next;}
                print $letter,"\t",$start[0],"\t",$end[-1],"\n";
                }

但我明白了:

A       20      40
A       60      75
A       90      100
A       200     205
A       211     270
B       1       10
B       50      200
B       300     350
B       400     500
B       600     711

但我只希望每个适当范围的第一个开始和结束

2 个答案:

答案 0 :(得分:3)

你没有说你是想要第一个或最后一个字母(或者如果你想把一个字母更改视为结束一个范围),所以我只是做第一个。

my $in_range;
my @ranges;
while (<>) {
    chomp;
    my ($letter, $start, $end, $value) = split /\t| /, $_;
    if ($value <= .3) {
        $in_range = undef;
    }
    elsif ($in_range) {
        $in_range->{'end'} = $end;
        push @{ $in_range->{'values'} }, $value;
    }
    else {
        $in_range = {
            'letter' => $letter,
            'start' => $start,
            'end' => $end,
            'values' => [ $value ],
        };
        push @ranges, $in_range;
    }
}

for my $range (@ranges) {
    print join( "\t",
        @$range{ qw/letter start end/ },
        scalar( @{ $range->{'values'} } ),
        join( ',', @{ $range->{'values'} } )
    ), "\n";
}

(根据评论更新以显示值)

答案 1 :(得分:1)

如何使用哈希?

#!/usr/bin/perl

use strict;
use warnings;

my %values;
while (<>) {
    chomp;
    my ($letter, $start, $end, $val) = split "\t| ";

    next if (defined $values{$letter}{skip_rest});

    if ($val > 0.3) {
        $values{$letter}{min} = $start
            if not defined $values{$letter}{min} or $values{$letter}{min} > $start;
        $values{$letter}{max} = $end
            if not defined $values{$letter}{max} or $values{$letter}{max} < $end;
    }
    elsif (defined $values{$letter}{min} and defined $values{$letter}{max}) {
        $values{$letter}{skip_rest} = "true";
    }
}

foreach my $letter (sort keys %values) {
    print "$letter\t$values{$letter}{min}\t$values{$letter}{max}\n";
}