Как я могу считать символы в Perl?
У меня есть следующий Perl script, подсчитывающий число Fs и Ts в строке:
my $str = "GGGFFEEIIEETTGGG";
my $ft_count = 0;
$ft_count++ while($str =~ m/[FT]/g);
print "$ft_count\n";
Есть ли более сжатый способ получить счет (другими словами, объединить строки 2 и 3)?
Ответы
Ответ 1
my $ft_count = $str =~ tr/FT//;
См. perlop.
Если REPLACEMENTLIST пуст, SEARCHLIST реплицируется. Последнее полезно для подсчета символы в классе & hellip;
$cnt = $sky =~ tr/*/*/; # count the stars in $sky
$cnt = tr/0-9//; # count the digits in $_
Здесь контрольный показатель:
use strict; use warnings;
use Benchmark qw( cmpthese );
my ($x, $y) = ("GGGFFEEIIEETTGGG" x 1000) x 2;
cmpthese -5, {
'tr' => sub {
my $cnt = $x =~ tr/FT//;
},
'm' => sub {
my $cnt = ()= $y =~ m/[FT]/g;
},
};
Rate tr m
Rate m tr
m 108/s -- -99%
tr 8118/s 7440% --
С ActiveState Perl 5.10.1.1006 на 32 Windows XP.
Разница кажется более выраженной с
C:\Temp> c:\opt\strawberry-5.12.1\perl\bin\perl.exe t.pl
Rate m tr
m 88.8/s -- -100%
tr 25507/s 28631% --
Ответ 2
Да, вы можете использовать секретный оператор CountOf:
my $ft_count = ()= $str =~ m/[FT]/g;
Ответ 3
Когда оператор "m" имеет флаг /g И выполняется в контексте списка, он возвращает список соответствующих подстрок. Таким образом, следующий способ:
my @ft_matches = $str =~ m/[FT]/g;
my $ft_count = @ft_matches; # count elements of array
Но это еще две строки. Другой более сложный трюк, который может сделать его короче:
my $ft_count = () = $str =~ m/[FT]/g;
"() =" заставляет "m" быть в контексте списка. Назначение списка с N элементами в список нулевых переменных на самом деле ничего не делает. Но тогда, когда это выражение присваивания используется в скалярном контексте ($ ft_count =...), правый оператор "=" возвращает количество элементов из его правой стороны - именно то, что вы хотите.
Это невероятно странно, когда он впервые встречается, но "idiom" - полезный трюк Perl, который нужно знать, "оценивать в контексте списка, а затем получать размер списка".
Примечание. У меня нет данных о том, какие из них более эффективны при работе с большими строками. На самом деле, я подозреваю, что ваш исходный код может быть лучшим в этом случае.
Ответ 4
Вы можете комбинировать строки 2, 3 и 4 в один так:
my $str = "GGGFFEEIIEETTGGG";
print $str =~ s/[FT]//g; #Output 4;