Je commence à plonger plus profondément dans Perl, mais j'ai du mal à écrire un code "perl-ly" au lieu d'écrire C en Perl. Comment puis-je modifier le code suivant pour utiliser plus d'idiomes Perl et comment devrais-je continuer à apprendre les idiomes?
Une explication de ce qu'elle fait: cette routine fait partie d'un module alignant les séquences d'ADN ou d'acides aminés ( Utiliser Needelman-Wunch si vous vous souciez de telles choses). Il crée deux matrices 2D, une pour stocker un score pour chaque position dans les deux séquences et une solution pour suivre le chemin du chemin afin que l'alignement de notation le plus élevé puisse être recréé plus tard. Cela fonctionne bien, mais je sais que je ne fais pas les choses très concises et clairement. P>
EDIT: STRUT> Ceci était pour une mission. Je l'ai terminé, mais je veux nettoyer mon code un peu. Les détails sur la mise en œuvre de l'algorithme peuvent être trouvés sur le site Web de la classe si aucun d'entre vous est intéressé. p>
6 Réponses :
Un changement simple consiste à utiliser Pour plus d'informations, voir la documentation Perl sur foreach Loops et le Opérateur de gamme . P> p> pour code> LOOPS comme ceci:
Je n'ai jamais compris cette syntaxe trop bien. Qu'est-ce que cela fait exactement?
@Jergason Il définit $ i code> à chacune des valeurs de
0 code> à
$ num_of_rows code>, inclusif.
@Jergason: .. code> est l'opérateur de gamme. Il renvoie une liste de valeurs (incrémentation par celles) de la première valeur à la seconde. Dans ce cas, c'est la liste
0, 1, 2 ... code> jusqu'à la valeur de
$ num_Rows code>.
Cela pourrait être plus facile si vous le lisez comme foreach code>. Je n'utilise généralement que
pour code> pour l'argument de style c-3-argument et
foreach code> pour la forme "boucle sur une liste". (Voir Perldoc Perlsyn)
J'ai aussi d'autres commentaires, mais voici la première observation: donc Voici comment je l'aurais écrit: p> $ auto -> {SEQ1} code> et
-> {SEQ2} CODE> Strings et vous continuez à accéder aux éléments individuels en utilisant
substr code>. Je préférerais les stocker comme des tableaux de caractères: p>
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;
}
}
}
En effet, l'algorithme nécessite une matrice 2D une rangée et une colonne plus grande que les longueurs des deux séquences.
J'ai aimé l'idée de diviser dans des tableaux de personnages. Les indices sont horriblement incertains, n'est-ce pas? Si SEQ1 a des caractères I et SEQ2 ont des caractères J, la matrice doit alors avoir des lignes I + 1 et des colonnes J + 1. Le score à chaque emplacement de la matrice est le maximum des scores provenant de l'emplacement directement au-dessus de + un coût d'intervalle, le voisin supérieur gauche + un score d'une correspondance ou d'une inadéquation à l'emplacement actuel et de l'emplacement directement sur la droite + un coût d'écart.
Boucle sur 0 .. $ NUM_OF_ROWS CODE>, vous n'avez pas besoin d'ajouter 1. Pendant que je suis à cela, je vais vous recommander de modifier les noms de variable sur
$ $ code> et < Code> $ cols code>, respectivement.
Pourquoi toutes les flèches de la déséroférience supplémentaires? $ matrice -> [$ Rail] -> [0] code> est équivalent à
$ matrice -> [$ ligne] [0] code>.
@DaoToad: Eh bien, c'est un choix de style.
La majorité de votre code est la manipulation de matrices 2D. Je pense que la plus grande amélioration serait de passer à l'utilisation de PDL si vous voulez faire beaucoup de choses avec des tableaux, en particulier si L'efficacité est une préoccupation. C'est un module Perl offrant un excellent support de réseau. Les routines sous-jacentes sont mises en œuvre en C pour une efficacité afin qu'elle soit aussi rapide. P>
Le Liste de diffusion PDL est le meilleur moyen de poser des questions sur les utilisateurs et le développeur PDL. communauté. La réponse est généralement rapide.
au lieu de la déséroférience de vos tableaux à deux dimensions, comme celui-ci: fais cela: p> aussi, vous faites aussi Beaucoup de déclarations si / alors / d'autre pour faire correspondre des sous-successes particulières: cela pourrait être mieux écrit sous forme d'instructions code> indiquant code> (équivalent de Perl5.10's équivalent du commutateur code>). Lisez à ce sujet à Perldoc Perlsyn : P>
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; }
}
Je n'avais pas entendu parler de donnée auparavant. C'est soigné.
La partie € code> n'est pas requise dans le
lorsque code> blocs, est-ce?
Ps. Ma vie n'a jamais été la même chose depuis que j'ai incorporé «la vérité» dans mon vocabulaire. Merci Stephen Colbert!
Ether: l'argument de la question est aliasé par $ _. $ _ est un argument gauche du match intelligent implicite lorsque. Voir 'Quand ("FOO")' à PerlSyn, exemple suivant.
Merci! Je suis assez nouveau à 5,10 et je n'ai pas encore utilisé l'opérateur Smart Match.
Commentaire incorrect supprimé et code corrigé; merci encore Alexandr.
Vous obtenez plusieurs suggestions concernant la syntaxe, mais je suggérerais également une approche plus modulaire, si, sans autre raison, la lisibilité du code. Il est beaucoup plus facile de trouver la vitesse de vitesse sur le code si vous pouvez percevoir la grande image avant de vous inquiéter des détails de bas niveau.
Votre méthode principale pourrait ressembler à ceci. P>
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.
Je conseillerais toujours de regarder La documentation sur ce module comprend un exemple de séquences d'ADN correspondant. Voici un exemple utilisant la matrice de similarité de Wikipedia . P> seqA pos: 7, seqB pos: 2 base 'G'
seqA pos: 6, seqB pos: 1 base 'T'
seqA pos: 4, seqB pos: 0 base 'A'
The maximum score is 100
Je l'ai examiné, mais c'était pour une mission qui nous oblige à mettre en œuvre l'algorithme nous-mêmes.
Pourquoi ai-je lu ceci la première fois comme "Comment puis-je modifier ceci en Perl" idiot '? "
Merci d'avoir mentionné le nom de l'algorithme! Je m'amuse de lire à ce sujet (et où proviennent les matrices de score et l'alignement de séquence en général, et ...)
Ouais, la bioinformatique a du CS fascinant derrière elle. J'apprends tout sur les arbres suffixe en ce moment, qui sont parfaits pour cartographier de petites séquences à un emplacement dans un génome de 3 milliards de bases +.
C'est drôle que vous voulez que votre Perl soit conforme lorsque Perl a toujours eu le slogan "Il y a plus d'une façon de le faire"
Hah. Oui, il y a une certaine ironie dans ce sens. Cependant, il y a plus d'une façon de le faire, mais certains sont beaucoup plus propres que d'autres. Je pense qu'il y a des moyens plus propres et plus concis de faire des choses similaires.
+1 Pour vouloir améliorer votre code, même après que vous ayez travaillé!
Un script Perl est "correct" si cela fait le travail avant que le patron vous incendie.