当前位置:  开发笔记 > 编程语言 > 正文

如何将其更改为"惯用"Perl?

如何解决《如何将其更改为"惯用"Perl?》经验,为你挑选了5个好方法。

我开始深入研究Perl,但是在编写"Perl-ly"代码时遇到了麻烦,而不是在Perl中编写C语言.如何更改以下代码以使用更多Perl习语,我应该如何学习习语?

只是解释它正在做什么:这个程序是一个模块的一部分,它对齐DNA或氨基酸序列(如果你关心这些事情,使用Needelman-Wunch).它创建了两个2d数组,一个用于存储两个序列中每个位置的分数,另一个用于跟踪路径,因此可以在以后重新创建得分最高的对齐.它工作正常,但我知道我并没有非常简洁明了地做事.

编辑:这是作业.我完成了它,但想要清理一下我的代码.如果您有兴趣,可以在课堂网站上找到有关实施算法的详细信息.

sub create_matrix {
    my $self = shift;
    #empty array reference
    my $matrix = $self->{score_matrix};
    #empty array ref
    my $path_matrix = $self->{path_matrix};
    #$seq1 and $seq2 are strings set previously
    my $num_of_rows = length($self->{seq1}) + 1;
    my $num_of_columns = length($self->{seq2}) + 1;

    #create the 2d array of scores
    for (my $i = 0; $i < $num_of_rows; $i++) {
        push(@$matrix, []);
        push(@$path_matrix, []);
        $$matrix[$i][0] = $i * $self->{gap_cost};
        $$path_matrix[$i][0] = 1;
    }

    #fill out the first row
    for (my $i = 0; $i < $num_of_columns; $i++) {
        $$matrix[0][$i] = $i * $self->{gap_cost};
        $$path_matrix[0][$i] = -1;
    }
    #flag to signal end of traceback
    $$path_matrix[0][0] = 2;
    #double for loop to fill out each row
    for (my $row = 1; $row < $num_of_rows; $row++) {
        for (my $column = 1; $column < $num_of_columns; $column++) {
            my $seq1_gap = $$matrix[$row-1][$column] + $self->{gap_cost};
            my $seq2_gap = $$matrix[$row][$column-1] + $self->{gap_cost};
            my $match_mismatch = $$matrix[$row-1][$column-1] + $self->get_match_score(substr($self->{seq1}, $row-1, 1), substr($self->{seq2}, $column-1, 1));
            $$matrix[$row][$column] = max($seq1_gap, $seq2_gap, $match_mismatch);

            #set the path matrix
            #if it was a gap in seq1, -1, if was a (mis)match 0 if was a gap in seq2 1
            if ($$matrix[$row][$column] == $seq1_gap) {
                $$path_matrix[$row][$column] = -1;
            }
            elsif ($$matrix[$row][$column] == $match_mismatch) {
                $$path_matrix[$row][$column] = 0;
            }
            elsif ($$matrix[$row][$column] == $seq2_gap) {
                $$path_matrix[$row][$column] = 1;
            }
        }
    }
}

FMc.. 9

您将获得有关语法的若干建议,但如果没有其他原因可以提供代码可读性,我还建议采用更模块化的方法.如果你能够在担心低级细节之前能够感知大局,那么在代码上加快速度要容易得多.

您的主要方法可能如下所示.

sub create_matrix {
    my $self = shift;
    $self->create_2d_array_of_scores;
    $self->fill_out_first_row;
    $self->fill_out_other_rows;
}

你也会有几个这样的小方法:

n_of_rows
n_of_cols
create_2d_array_of_scores
fill_out_first_row
fill_out_other_rows

你可以通过定义更小的方法 - getter,setter等来进一步研究它.此时,您的中级方法create_2d_array_of_scores根本不会直接触及底层数据结构.

sub matrix      { shift->{score_matrix} }
sub gap_cost    { shift->{gap_cost}     }

sub set_matrix_value {
    my ($self, $r, $c, $val) = @_;
    $self->matrix->[$r][$c] = $val;
}

# Etc.

用于推广自我记录代码的+1:新的成语 (3认同)


FMc.. 8

一个简单的改变是使用这样的for循环:

for my $i (0 .. $num_of_rows){
    # Do stuff.
}

有关详细信息,请参阅有关foreach循环和范围运算符的Perl文档.



1> FMc..:

您将获得有关语法的若干建议,但如果没有其他原因可以提供代码可读性,我还建议采用更模块化的方法.如果你能够在担心低级细节之前能够感知大局,那么在代码上加快速度要容易得多.

您的主要方法可能如下所示.

sub create_matrix {
    my $self = shift;
    $self->create_2d_array_of_scores;
    $self->fill_out_first_row;
    $self->fill_out_other_rows;
}

你也会有几个这样的小方法:

n_of_rows
n_of_cols
create_2d_array_of_scores
fill_out_first_row
fill_out_other_rows

你可以通过定义更小的方法 - getter,setter等来进一步研究它.此时,您的中级方法create_2d_array_of_scores根本不会直接触及底层数据结构.

sub matrix      { shift->{score_matrix} }
sub gap_cost    { shift->{gap_cost}     }

sub set_matrix_value {
    my ($self, $r, $c, $val) = @_;
    $self->matrix->[$r][$c] = $val;
}

# Etc.


用于推广自我记录代码的+1:新的成语

2> FMc..:

一个简单的改变是使用这样的for循环:

for my $i (0 .. $num_of_rows){
    # Do stuff.
}

有关详细信息,请参阅有关foreach循环和范围运算符的Perl文档.


@Jergason:`..`是范围运算符.它返回从第一个值到第二个值的值列表(以1递增).在这种情况下,它是列表"0,1,2 ......",直到`$ num_rows`的值.

3> Sinan Ünür..:

我还有其他一些评论,但这是第一个观察:

my $num_of_rows = length($self->{seq1}) + 1;
my $num_of_columns = length($self->{seq2}) + 1;

所以,$self->{seq1}并且$self->{seq2}是字符串,你继续使用substr.我宁愿将它们存储为字符数组:

$self->{seq1} = [ split //, $seq1 ];

这是我写的方式:

sub create_matrix {
    my $self = shift;

    my $matrix      = $self->{score_matrix};
    my $path_matrix = $self->{path_matrix};

    my $rows = @{ $self->{seq1} };
    my $cols = @{ $self->{seq2} };

    for my $row (0 .. $rows) {
        $matrix->[$row]->[0] =  $row * $self->{gap_cost};
        $path_matrix->[$row]->[0] = 1;
    }

    my $gap_cost = $self->{gap_cost};

    $matrix->[0] = [ map { $_ * $gap_cost } 0 .. $cols ];
    $path_matrix->[0] = [ (-1) x ($cols + 1) ];

    $path_matrix->[0]->[0] = 2;

    for my $row (1 .. $rows) {
        for my $col (1 .. $cols) {
            my $gap1 = $matrix->[$row - 1]->[$col] + $gap_cost;
            my $gap2 = $matrix->[$row]->[$col - 1] + $gap_cost;
            my $match_mismatch =
                $matrix->[$row - 1]->[$col - 1] +
                $self->get_match_score(
                    $self->{seq1}->[$row - 1],
                    $self->{seq2}->[$col - 1]
                );

            my $max = $matrix->[$row]->[$col] =
                max($gap1, $gap2, $match_mismatch);

            $path_matrix->[$row]->[$col] = $max == $gap1
                    ? -1
                    : $max == $gap2
                    ? 1
                    : 0;
            }
        }
    }


为什么所有额外的解除引用箭头?`$ matrix - > [$ row] - > [0]`相当于`$ matrix - > [$ row] [0]`.

4> Ether..:

而不是像这样取消引用你的二维数组:

$$path_matrix[0][0] = 2;

做这个:

$path_matrix->[0][0] = 2;

此外,你正在做很多if/then/else语句来匹配特定的子序列:这可以更好地写成given语句(perl5.10相当于C的switch).在perldoc perlsyn上阅读它:

given ($matrix->[$row][$column])
{
    when ($seq1_gap)       { $path_matrix->[$row][$column] = -1; }
    when ($match_mismatch) { $path_matrix->[$row][$column] = 0; }
    when ($seq2_gap)       { $path_matrix->[$row][$column] = 1; }
}



5> ire_and_curs..:

您的大多数代码都在操纵2D数组.我认为,如果你想对阵列做很多事情,那么最大的改进就是转向使用PDL,特别是如果要考虑效率问题.它是一个Perl模块,可提供出色的阵列支持.底层例程在C中实现以提高效率,因此它也很快.

推荐阅读
牛尾巴2010
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有