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