tr
文字列内の文字を数えようとしていますが、演算子を使用して1文字を数える簡単な解決策を見つけました。今、私はこれをaからzまでのすべての文字で実行したいと思います。tr///
次の解決策は、すべての文字に一致するため機能しません。
my @chars = ('a' .. 'z');
foreach my $c (@chars)
{
$count{$c} = ($text =~ tr/$c//);
}
でchar変数を正しく使用するにはどうすればよいtr///
ですか?
tr
文字列内の文字を数えようとしていますが、演算子を使用して1文字を数える簡単な解決策を見つけました。今、私はこれをaからzまでのすべての文字で実行したいと思います。tr///
次の解決策は、すべての文字に一致するため機能しません。
my @chars = ('a' .. 'z');
foreach my $c (@chars)
{
$count{$c} = ($text =~ tr/$c//);
}
でchar変数を正しく使用するにはどうすればよいtr///
ですか?
tr///
変数でラップしない限り、変数は機能しませんeval
しかし、これを行うためのより良い方法があります:
$count{$_} = () = $text =~ /$_/g for 'a' .. 'z';
TIMTOWTDIの場合:
$count{$_}++ for grep /[a-z]/i, split //, $text;
tr
変数の補間をサポートしていません(検索リストでも置換リストでも)。変数を使用する場合は、次を使用する必要がありますeval()
。
$count{$c} = eval "\$text =~ tr/$c/$c/";
そうは言っても、より効率的な(そして安全な)アプローチは、文字列内の文字を単純に反復し、各文字のカウンターをインクリメントすることです。例:
my %count = map { $_ => 0 } 'a' .. 'z';
for my $char (split //, $text) {
$count{$char}++ if defined $count{$char};
}
のperldocを見るtr/SEARCHLIST/REPLACEMENTLIST/cdsr
と、セクションの一番下に次のように表示されます。
文字変換テーブルはコンパイル時に作成されるため、SEARCHLISTもREPLACEMENTLISTも二重引用符の補間を受けません。つまり、変数を使用する場合は、eval()を使用する必要があります。
eval "tr/$oldlist/$newlist/";
die $@ if $@;
eval "tr/$oldlist/$newlist/, 1" or die $@;
したがって、新しいSEARCHLISTを生成するには評価が必要になります。
これは非常に非効率的になります...コードはきれいに感じるかもしれませんが、完全な文字列を26回処理しています。また、大文字は数えていません。
文字列を1回ステップ実行し、見つかった文字ごとにカウンターをインクリメントする方がよいでしょう。
perlopのドキュメントから:
tr/AAA/XYZ/
AからXに音訳します。
文字変換テーブルはコンパイル時に作成されるため、SEARCHLISTもREPLACEMENTLISTも二重引用符の補間を受けません。つまり、変数を使用する場合は、eval()を使用する必要があります。
s///
または、次のように演算子を使用することもできます。
foreach my $c (@chars) {
$count{$c} += ($text =~ s/$c//g);
}
http://www.perlmonks.org/?node_id=446003に基づいていくつかの変更を加えた私のソリューション
sub lowerLetters {
my $string = shift;
my %table;
@table{split //, $letters_uc} = split //, $letters_lc;
my $table_re = join '|', map { quotemeta } reverse sort keys %table;
$string =~ s/($table_re)/$table{$1}/g;
return if not defined $string;
return $string;
}
代わりに使用することをお勧めしますs
。置換はよりもはるかに強力ですtr
私の解決策:
$count{$c} =~ s/\$search/$replace/g;
g
最後に「グローバルに使用する」という意味です。
見る: