Ich habe mehrere Stellen, wo ich meine Saite in mehrere Teile schneiden möchte.
Beispielsweise:
$string= "AACCAAGTAA";
@cut_places= {0,4, 8 };
Meine $string
sollte so aussehen: AACC AAGT AA;
Wie kann ich das machen?
Antworten:
7 für die Antwort № 1Um ein Array aufzufüllen, verwenden Sie runde Klammern, nicht geschweifte Klammern (sie werden für Hash-Referenzen verwendet).
Ein möglicher Weg ist zu verwenden Teilstr wo das erste Argument die Position ist, also dukann die Array-Elemente verwenden. Sie müssen nur die Länge berechnen, indem Sie die Position von der folgenden subtrahieren; und um die letzte Länge berechnen zu können, brauchst du auch die Länge der ganzen Saite:
#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
my $string = "AACCAAGTAA";
my @cut_places = (0, 4, 8);
push @cut_places, length $string;
my @parts = map {
substr $string, $cut_places[$_], $cut_places[$_+1] - $cut_places[$_]
} 0 .. $#cut_places - 1;
say for @parts;
Wenn das ursprüngliche Array Längen statt Positionen enthält, wäre der Code viel einfacher.
#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
my $string = "AACCAAGTAA";
my @lengths = (4, 4, 2); # 4, 4, 4 would work, too
my @parts = unpack join("", map "A$_", @lengths), $string;
say for @parts;
Sehen auspacken für Details.
0 für die Antwort № 2
Hier ist eine Lösung, die mit der Berechnung beginnt Vorwärts Unterschiede in der Liste der Positionen. Die Länge der Zeichenkette wird zuerst an das Ende der Liste angehängt, von der sie sich nicht bereits über die gesamte Zeichenkette erstreckt
Die Unterschiede werden dann verwendet, um ein unpack
Formatzeichenkette, die zum Erstellen der erforderlichen Folge von Teilstrings verwendet wird.
Ich habe die Funktionalität als geschrieben do
Block, der bei Bedarf einfach in ein Unterprogramm umgewandelt werden könnte.
use strict;
use warnings "all";
use feature "say";
my $string = "AACCAAGTAA";
my @cut_places = ( 0, 4, 8 );
my @parts = do {
my @places = @cut_places;
my $len = length $string;
push @places, $len unless $places[-1] >= $len;
my @w = map { $places[$_]-$places[$_-1] } 1 .. $#places;
my $patt = join " ", map { "A$_" } @w;
unpack $patt, $string;
};
say "@parts";
Ausgabe
AACC AAGT AA
0 für die Antwort № 3
Berechnen Sie zuerst die Länge der benötigten Teile, dann sind alle Methoden einfacher. Hier wird Regex verwendet
use warnings;
use strict;
use feature "say";
my $string = "AACCAAGTAA";
my @pos = (0, 4, 8);
my @lens = do {
my $prev = shift @pos;
"$prev", map { my $e = $_ - $prev; $prev = $_; $e } @pos;
};
my $patt = join "", map { "(.{".$_."})" } @lens;
my $re = qr/$patt/;
my @parts = grep { /./ } $string =~ /$re(.*)/g;
say for @parts;
Die Längen @lens
werden berechnet, indem die aufeinanderfolgenden Positionen, 2-1, 3-2 (usw.), subtrahiert werden. ich benutze do
nur damit das @prev
Variable, die an anderer Stelle nicht benötigt wird, "verschmutzt" den Rest des Codes nicht. Das "$prev"
wird so zitiert, dass es zuerst ausgewertet wird, bevor es sich ändert map
.
Die von Regex zurückgegebenen Übereinstimmungen werden übergeben grep
durch die leere Zeichenfolge (n) herauszufiltern 0
Position (oder wenn aufeinanderfolgende Positionen gleich sind).
Dies funktioniert für Positionsarrays beliebiger Länge, solange Positionen mit einem String konsistent sind.