/ / Wie teilt man einen String mit mehreren Positionen mit Perl? - Perl, Teilzeichenfolge, Teilstr

Wie teilt man einen String mit mehreren Positionen mit Perl? - Perl, Teilzeichenfolge, Teilstr

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 № 1

Um 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.