我有几个地方想要在几个部分剪下我的弦 例如:
$string= "AACCAAGTAA";
@cut_places= {0,4, 8 };
我的$string
应如下所示:AACC AAGT AA;
我怎么能这样做?
答案 0 :(得分:7)
要填充数组,请使用圆括号,而不是大括号(它们用于散列引用)。
一种可能的方法是使用substr,其中第一个参数是位置,因此您可以使用数组元素。你只需要通过从下一个中减去位置来计算长度;并且为了能够计算最后的长度,你也需要整个字符串的长度:
#!/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;
如果原始数组包含长度而不是位置,则代码将更容易。
#!/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;
有关详细信息,请参阅unpack。
答案 1 :(得分:0)
首先计算出所需部件的长度,然后所有方法都更容易。这里使用了正则表达式
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;
通过减去连续位置2-1,3-2(等)来计算长度@lens
。我只使用do
,以便其他地方不需要的@prev
变量不会污染"其余的代码。
引用"$prev"
以便在map
更改之前首先对其进行评估。
正则表达式返回的匹配项通过grep
传递,以过滤由0
位置引起的空字符串(或每当连续位置相同时)。
这适用于任何长度的位置数组,只要位置与字符串一致即可。
答案 2 :(得分:0)
这是一个解决方案,首先计算位置列表中的前向差异。字符串的长度首先附加到列表的末尾,它还没有跨越完整的字符串
然后使用差异来构建unpack
格式字符串,用于构建所需的子字符串序列。
我已将该功能编写为do
块,如果需要,可以很容易地转换为子例程。
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";
AACC AAGT AA