在 perl 中保存音译表

发布于 2024-10-21 03:46:10 字数 497 浏览 0 评论 0原文

我想用 0 音译 1 - 8 的数字,但在编译时不知道数字。由于音译不会插​​入变量,所以我这样做:

@trs = (sub{die},sub{${$_[0]} =~ tr/[0,1]/[1,0]/},sub{${$_[0]} =~ tr/[0,2]/[2,0]/},sub{${$_[0]} =~ tr/[0,3]/[3,0]/},sub{${$_[0]} =~ tr/[0,4]/[4,0]/},sub{${$_[0]} =~ tr/[0,5]/[5,0]/},sub{${$_[0]} =~ tr/[0,6]/[6,0]/},sub{${$_[0]} =~ tr/[0,7]/[7,0]/},sub{${$_[0]} =~ tr/[0,8]/[8,0]/});

然后将其索引为:

$trs[$character_to_transliterate](\$var_to_change);

如果有人能给我指出一个最好看的解决方案,我将不胜感激。

I want to transliterate digits from 1 - 8 with 0 but not knowing the number at compile time. Since transliterations do not interpolate variables I'm doing this:

@trs = (sub{die},sub{${$_[0]} =~ tr/[0,1]/[1,0]/},sub{${$_[0]} =~ tr/[0,2]/[2,0]/},sub{${$_[0]} =~ tr/[0,3]/[3,0]/},sub{${$_[0]} =~ tr/[0,4]/[4,0]/},sub{${$_[0]} =~ tr/[0,5]/[5,0]/},sub{${$_[0]} =~ tr/[0,6]/[6,0]/},sub{${$_[0]} =~ tr/[0,7]/[7,0]/},sub{${$_[0]} =~ tr/[0,8]/[8,0]/});

and then index it like:

$trs[$character_to_transliterate](\$var_to_change);

I would appreciate if anyone can point me to a best looking solution.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

三生路 2024-10-28 03:46:10

每当你重复自己时,你应该看看你正在做的事情是否可以循环完成。由于 tr 在编译时创建其表,因此您可以使用 eval 在运行时访问编译器:

my @trs = (sub {die}, map {eval "sub {\$_[0] =~ tr/${_}0/0$_/}"} 1 .. 8);

my $x = 123;

$trs[2]($x);

print "$x\n"; # 103

这里也不需要使用引用,子例程参数已经通过参考。

如果您不想使用字符串 eval,则需要使用支持运行时修改的构造。为此,您可以使用 s/// 运算符:

sub subst {$_[0] =~ s/($_[1]|0)/$1 ? 0 : $_[1]/ge}

my $z = 1230;

subst $z => 2;

print "$z\n"; # 1032

tr/// 构造比 s/// 更快,因为后者支持正则表达式。

Any time that you are repeating yourself, you should see if what you are doing can be done in a loop. Since tr creates its tables at compile time, you can use eval to access the compiler at runtime:

my @trs = (sub {die}, map {eval "sub {\$_[0] =~ tr/${_}0/0$_/}"} 1 .. 8);

my $x = 123;

$trs[2]($x);

print "$x\n"; # 103

There is also no need to use references here, subroutine arguments are already passed by reference.

If you do not want to use string eval, you need to use a construct that supports runtime modification. For that you can use the s/// operator:

sub subst {$_[0] =~ s/($_[1]|0)/$1 ? 0 : $_[1]/ge}

my $z = 1230;

subst $z => 2;

print "$z\n"; # 1032

The tr/// construct is faster than s/// since the latter supports regular expressions.

七度光 2024-10-28 03:46:10

我建议简单地放弃 tr,转而使用实际上允许一点元编程的东西,例如 s///。例如:

# Replace $to_swap with 0 and 0 with $to_swap, and leave
# everything else alone.
sub swap_with_0 {
    my ($digit, $to_swap) = @_;
    if ($digit == $to_swap) {
        return 0;
    } elsif ($digit == 0) {
        return $to_swap;
    } else {
        return $digit;
    }
}

# Swap 0 and $to_swap throughout $string
sub swap_digits {
    my ($string, $to_swap) = @_;
    $string =~ s/([0$to_swap])/swap_with_0($1, $to_swap)/eg;
    return $string;
}

这非常简单。 :)

I'd suggest simply ditching tr in favor of something that actually permits a little bit of metaprogramming like s///. For example:

# Replace $to_swap with 0 and 0 with $to_swap, and leave
# everything else alone.
sub swap_with_0 {
    my ($digit, $to_swap) = @_;
    if ($digit == $to_swap) {
        return 0;
    } elsif ($digit == 0) {
        return $to_swap;
    } else {
        return $digit;
    }
}

# Swap 0 and $to_swap throughout $string
sub swap_digits {
    my ($string, $to_swap) = @_;
    $string =~ s/([0$to_swap])/swap_with_0($1, $to_swap)/eg;
    return $string;
}

which is surprisingly straightforward. :)

滥情稳全场 2024-10-28 03:46:10

这是一个使用替换而不是音译的简短子例程:

sub swap_digits {
    my ($str, $digit) = @_;
    $str =~ s{ (0) | $digit }{ defined $1 ? $digit : 0 }gex;
    return $str;
}

Here's a short subroutine that uses substitution instead of transliteration:

sub swap_digits {
    my ($str, $digit) = @_;
    $str =~ s{ (0) | $digit }{ defined $1 ? $digit : 0 }gex;
    return $str;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文