/ / Jak podciągnąć łańcuch znaków z kilkoma pozycjami za pomocą Perla? - perl, substring, substr

Jak podciąć łańcuch z kilkoma pozycjami za pomocą języka Perl? - perl, podciąg, substr

Mam kilka miejsc, w których chcę ciąć strunę na kilka części.
Na przykład:

$string= "AACCAAGTAA";
@cut_places= {0,4, 8 };

Mój $string powinien wyglądać tak: AACC AAGT AA;
Jak mogę to zrobić?

Odpowiedzi:

7 dla odpowiedzi № 1

Aby zapełnić tablicę, użyj okrągłych nawiasów, a nie nawiasów klamrowych (są one używane w odniesieniu do odnośników mieszania).

Jednym z możliwych sposobów jest użycie substr gdzie pierwszym argumentem jest pozycja, a więc tymoże używać elementów tablicy. Wystarczy obliczyć długość, odejmując pozycję od następnej; i aby móc obliczyć ostatnią długość, potrzebujesz także długości całego ciągu:

#!/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;

Gdyby oryginalna tablica zawierała długości zamiast pozycji, kod byłby znacznie łatwiejszy.

#!/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;

Widzieć rozpakować dla szczegółów.


0 dla odpowiedzi nr 2

Oto rozwiązanie, które rozpoczyna się od obliczenia różnice naprzód na liście pozycji. Długość łańcucha jest najpierw dołączana na końcu listy, która nie obejmuje już całego łańcucha

Różnice są następnie wykorzystywane do budowania unpack ciąg formatujący, który jest używany do budowania wymaganej sekwencji podciągów.

Funkcjonalność napisałem jako do blok, który byłby prosty do konwersji na podprogram w razie potrzeby.

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";

wydajność

AACC AAGT AA

0 dla odpowiedzi № 3

Najpierw określ długość potrzebnych części, a następnie wszystkie metody są łatwiejsze. Tutaj używa się wyrażenia regularnego

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;

Długości @lens są obliczane przez odjęcie kolejnych pozycji, 2-1, 3-2 (itd.). używam do tylko po to, aby @prev zmienna, niepotrzebna gdzie indziej, nie „zanieczyszcza” reszty kodu. The "$prev" jest cytowany, aby był oceniany jako pierwszy, zanim się zmieni map.

Dopasowania zwrócone przez wyrażenie regularne są przekazywane grep aby odfiltrować pusty ciąg (ciągi) z powodu 0 pozycja (lub zawsze, gdy kolejne pozycje są takie same).

Działa to dla tablic pozycji o dowolnej długości, o ile pozycje są zgodne z ciągiem znaków.